swift 给UICollectionView的section设置不一样的背景颜色|8月更文挑战

先看下效果图:markdown

Simulator Screen Shot - iPhone 12 Pro Max - 2021-07-30 at 16.46.25.png

你们都是道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试试效果布局

使用案列

一、建立一个UICollectionViewcollectionViewLayout使用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

相关文章
相关标签/搜索