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

相關文章
相關標籤/搜索