給UICollectionView的Section設置背景顏色

UICollectionView沒有設置Section背景顏色的屬性。需要自定義布局對象(UICollectionViewLayout)

Section的背景顏色屬于UICollectionView的 Decoration(裝飾)視圖 。
Decoration 視圖無法通過數(shù)據(jù)源來設置,而是由布局對象來定義和管理。

無論是定義 Cell 視圖、Supplementary 視圖還是 Decoration 視圖都是通過它們的 attributes(UICollectionViewLayoutAttributes)來定義的。

1.由于沒有backgroundColor屬性。需要自定義UICollectionViewLayoutAttributes

private class FLFoodCategoryCollectionViewLayoutAttributes: UICollectionViewLayoutAttributes {
    var backgroundColor = UIColor.clear
}

2.Decoration視圖屬于UICollectionReusableView 的子類,但Decoration 視圖無法通過數(shù)據(jù)源來設置,也沒有 dequeue相關的方法,所以自定義的屬性是通過 UICollectionReusableView 的 apply 方法在 UICollectionView 布局時生效。

private class FLFoodCategoryCollectionReusableView: UICollectionReusableView {
    
    private override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
        guard let attr =  layoutAttributes as? FLFoodCategoryCollectionViewLayoutAttributes  else {
            return
        }
        self.backgroundColor = attr.backgroundColor
    }
}

3.添加自定義的布局對象到Decoration 視圖上

  • 注冊Decoration 視圖
  • 定義Decoration視圖的布局attributes
  • layoutAttributesForElementsInRect返回 Decoration 視圖的布局 attributes
class FLFoodCategoryCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
    private var decorationViewAttrs: [UICollectionViewLayoutAttributes] = []
    
    override init() {
        super.init()
        
        //注冊
        self.register(FLFoodCategoryCollectionReusableView.classForCoder(), forDecorationViewOfKind: "SectionBackground")

    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    
    override func prepare() {
        super.prepare()
        
        //Section個數(shù)
        guard let numberOfSections = self.collectionView?.numberOfSections,
            let delegate = self.collectionView?.delegate as? FLFoodCategoryCollectionViewDelegateFlowLayout
            else {
                return
        }
        
        self.decorationViewAttrs.removeAll()
        for section in 0..<numberOfSections {
            guard let numberOfItems = self.collectionView?.numberOfItems(inSection: section),
                numberOfItems > 0,
                let firstItem = self.layoutAttributesForItem(at: IndexPath(item: 0, section: section)),
                let lastItem = self.layoutAttributesForItem(at: IndexPath(item: numberOfItems - 1, section: section)) else {
                    continue
            }
            
            var sectionInset = self.sectionInset
            if let inset = delegate.collectionView?(self.collectionView!, layout: self, insetForSectionAt: section) {
                sectionInset = inset
            }
            
            var sectionFrame = firstItem.frame.union(lastItem.frame)
            sectionFrame.origin.x = 0
            sectionFrame.origin.y -= sectionInset.top
            
            if self.scrollDirection == .horizontal {
                sectionFrame.size.width += sectionInset.left + sectionInset.right
                sectionFrame.size.height = self.collectionView!.frame.height
            } else {
                sectionFrame.size.width = self.collectionView!.frame.width
                sectionFrame.size.height += sectionInset.top + sectionInset.bottom
            }
            
            // 2、定義視圖屬性
            let attr = FLFoodCategoryCollectionViewLayoutAttributes(forDecorationViewOfKind: "SectionBackground", with: IndexPath(item: 0, section: section))
            attr.frame = sectionFrame
            attr.zIndex = -1
            attr.backgroundColor = delegate.collectionView(self.collectionView!, layout: self, backgroundColorForSectionAt: section)
            self.decorationViewAttrs.append(attr)
        }
    }

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var attrs = super.layoutAttributesForElements(in: rect)
        attrs?.append(contentsOf: self.decorationViewAttrs.filter {
            return rect.intersects($0.frame)
        })
        return attrs // 3、返回
    }

    
}

4.為視圖布局增加修改顏色的屬性方法

protocol FLFoodCategoryCollectionViewDelegateFlowLayout: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, backgroundColorForSectionAt section: Int) -> UIColor
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容