先看下效果圖: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