先看下效果图:markdown
你们都是道UICollectionView
没有提供相关的属性或方法去设置section不一样的背景颜色,若是想让UICollectionView
的section显示不一样的背景颜色,就须要自定义一个新的布局。
app
UICollectionViewSectionColorReusableView
继承自UICollectionReusableView
,用来做为各个分组的背景视图class UICollectionViewSectionColorReusableView: UICollectionReusableView {
override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
super.apply(layoutAttributes)
if let att = layoutAttributes as? UICollectionViewSectionColorLayoutAttributes {
backgroundColor = att.sectionBgColor
}
}
}
复制代码
UICollectionViewSectionColorLayoutAttributes
继承UICollectionViewLayoutAttributes
,里面添加一个sectionBgColor
属性,用来表示section的背景颜色class UICollectionViewSectionColorLayoutAttributes: UICollectionViewLayoutAttributes {
var sectionBgColor: UIColor?
}
复制代码
UICollectionViewSectionColorFlowLayout
继承UICollectionViewFlowLayout
,在这里计算及返回各个分组背景视图的布局属性(位置、尺寸、颜色)class UICollectionViewSectionColorFlowLayout: UICollectionViewFlowLayout {
var decorationViewAttrs = [UICollectionViewSectionColorLayoutAttributes]()
override init() {
super.init()
register(UICollectionViewSectionColorReusableView.self, forDecorationViewOfKind: "UICollectionViewSectionColorReusableView")
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepare() {
super.prepare()
//Section个数
guard let collectionView = collectionView else { return }
let numberOfSections = collectionView.numberOfSections
guard let delegate = collectionView.delegate as? UICollectionViewSectionColorDelegateFlowLayout
else {
return
}
decorationViewAttrs.removeAll()
for section in 0..<numberOfSections {
let numberOfItems = collectionView.numberOfItems(inSection: section)
guard numberOfItems > 0,
let firstItem = layoutAttributesForItem(at: IndexPath(item: 0, section: section)),
let lastItem = layoutAttributesForItem(at: IndexPath(item: numberOfItems - 1, section: section)) else {
continue
}
var sectionInset = self.sectionInset
if let inset = delegate.collectionView?(collectionView, layout: self, insetForSectionAt: section) {
sectionInset = inset
}
var sectionFrame = firstItem.frame.union(lastItem.frame)
sectionFrame.origin.x = 0
sectionFrame.origin.y -= sectionInset.top
if scrollDirection == .horizontal {
sectionFrame.size.width += sectionInset.left + sectionInset.right
sectionFrame.size.height = collectionView.frame.height
} else {
sectionFrame.size.width = collectionView.frame.width
sectionFrame.size.height += sectionInset.top + sectionInset.bottom
}
// 二、定义视图属性
let attr = UICollectionViewSectionColorLayoutAttributes(forDecorationViewOfKind: "UICollectionViewSectionColorReusableView", with: IndexPath(item: 0, section: section))
attr.frame = sectionFrame
attr.zIndex = -1
attr.sectionBgColor = delegate.collectionView?(collectionView, layout: self, backgroundColor: section)
decorationViewAttrs.append(attr)
}
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil }
var allAttributes = [UICollectionViewLayoutAttributes]()
allAttributes.append(contentsOf: attributes)
for att in decorationViewAttrs {
if rect.intersects(att.frame) {
allAttributes.append(att)
}
}
return allAttributes
}
}
复制代码
@objc protocol UICollectionViewSectionColorDelegateFlowLayout: UICollectionViewDelegateFlowLayout {
@objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, backgroundColor section: Int) -> UIColor
}
复制代码
以上就是自定义布局的全过程,总结一下就四步:
一、自定义一个UICollectionViewSectionColorReusableView
继承自UICollectionReusableView
,用来做为各个分组的背景视图
二、自定义一个UICollectionViewSectionColorLayoutAttributes
继承UICollectionViewLayoutAttributes
,里面添加一个sectionBgColor
属性,用来表示section的背景颜色
三、自定义一个UICollectionViewSectionColorFlowLayout
继承UICollectionViewFlowLayout
,在这里计算及返回各个分组背景视图的布局属性(位置、尺寸、颜色)
四、新增一个协议方法,用于在外面经过该方法设置背景色ide
如今咱们就来写个demo试试效果布局
UICollectionView
,collectionViewLayout
使用UICollectionViewSectionColorFlowLayout
private lazy var collectionView: UICollectionView = {
let layout = UICollectionViewSectionColorFlowLayout()
layout.itemSize = CGSize(width: (UIScreen.main.bounds.size.width - 51) / 4, height: 65)
layout.minimumLineSpacing = 10
layout.minimumInteritemSpacing = 10
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
let collectionView = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: layout)
collectionView.backgroundColor = .gray
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.self,
forCellWithReuseIdentifier: "UICollectionViewCell")
collectionView.showsVerticalScrollIndicator = false
return collectionView
}()
复制代码
UICollectionViewSectionColorDelegateFlowLayout
协议,设置不一样section背景颜色extension ViewController: UICollectionViewSectionColorDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, backgroundColor section: Int) -> UIColor {
switch section {
case 0:
return .green
case 2:
return .blue
case 3:
return .cyan
case 4:
return .purple
default:
return .orange
}
}
}
复制代码
到此就结束了ui