6. UICollectionView Decoration View

6. UICollectionView Decoration View

UICollectionView 容許咱們爲每個section、cell甚至是整個collectionView添加一個裝飾視圖。這玩意怎麼說呢,就是添加了一些可複用視圖,視圖的frame能夠隨意設置,劃重點是隨意設置。git

1.給section添加一張背景圖片

實現裝飾視圖須要自定義layout,這裏選擇集成UICollectionViewFlowLayout,爲了省去cell的佈局實現swift

class CZDecorationFlowLayout: UICollectionViewFlowLayout {
    let decorationViewKind = "CZDecorationView"
    var itemsAttribute = [UICollectionViewLayoutAttributes]()
    var cz_delegate: CZDecorationFlowLayoutDelegate?
    
    override func prepare() {
        super.prepare()
        // 註冊裝飾視圖
        self.register(CZDecorationView.self, forDecorationViewOfKind: decorationViewKind)
        // 獲取section數量
        let sections = self.collectionView?.numberOfSections ?? 0
        
        // 給每個section添加裝飾視圖的佈局屬性
        for i in 0..<sections {
            let attribute = CZDecorationAttributes.init(forDecorationViewOfKind: decorationViewKind, with: IndexPath(item: 0, section: i))
            attribute.zIndex = -1
            attribute.imageName = self.cz_delegate?.layout(self, decorationImageAt: i)
            
            if let count = self.collectionView?.numberOfItems(inSection: i), count > 0 {
                let firstItem = self.layoutAttributesForItem(at: IndexPath(item: 0, section: i))
                let lastItem = self.layoutAttributesForItem(at: IndexPath(item: (count - 1), section: i))
                let height = lastItem!.frame.maxY - firstItem!.frame.minY
                attribute.frame = CGRect(x: 0, y: firstItem!.frame.minY, width: self.collectionView!.frame.size.width, height: height)
                self.itemsAttribute.append(attribute)
            }
        }
        
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        var attributes = super.layoutAttributesForElements(in: rect)
        for attribute in self.itemsAttribute {
            if rect.intersects(attribute.frame) {
                attributes?.append(attribute)
            }
        }
        return attributes
    }
}

重寫prepare方法,此時必定要調用super.prepare(),不然會出問題。這裏的代理是爲了獲取不一樣section中的圖片,裝飾視圖的frame能夠隨意設置,由於要給section添加背景,咱們選擇從第一個cell到最後一個cell,且寬度等於collectionView的寬度,將佈局屬性添加到數組中,後續在layoutAttributesForElements(in rect: CGRect)中將其追加到collectionView子視圖的佈局屬性數組中數組

class CZDecorationView: UICollectionReusableView {

    var imageView = UIImageView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.addSubview(imageView)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
        self.imageView.frame = layoutAttributes.bounds
        let attributes = layoutAttributes as! CZDecorationAttributes
        if let name = attributes.imageName {
            self.imageView.image = UIImage(named: name)
        }
    }
}

最重要的是apply(_ layoutAttributes: UICollectionViewLayoutAttributes),在這裏咱們將對視圖中的子視圖設置數據。app

到此就完成了一個section的背景添加
sectiont添加背景圖片ide

2.給cell添加背景圖片

對於上面的代碼,咱們只須要改一下裝飾視圖的佈局屬性便可佈局

let itemCount = self.collectionView?.numberOfItems(inSection: i) ?? 0
for item in 0..<itemCount {
    let indexPath = IndexPath(item: item, section: i)
    let attribute = CZDecorationAttributes.init(forDecorationViewOfKind: decorationViewKind, with: indexPath)
    attribute.zIndex = -1
    attribute.imageName = self.cz_delegate?.layout(self, decorationImageAt: indexPath)
    let itemAttributes = self.layoutAttributesForItem(at: indexPath)!
    attribute.frame = itemAttributes.frame
    self.itemsAttribute.append(attribute)
}

cell添加背景圖片

3.collectionView可滾動範圍添加背景圖片

if let itemCountInSection = self.collectionView?.numberOfItems(inSection: (sections - 1)), itemCountInSection > 0 {
    let firstItem = self.layoutAttributesForItem(at: IndexPath(item: 0, section: 0))
    let lastItem = self.layoutAttributesForItem(at: IndexPath(item: (itemCountInSection - 1), section: (sections - 1)))
    let indexPath = IndexPath(item: 0, section: 0)
    let attribute = CZDecorationAttributes.init(forDecorationViewOfKind: decorationViewKind, with: indexPath)
    attribute.zIndex = -1
    attribute.imageName = "6"
    let height = lastItem!.frame.maxY - firstItem!.frame.minY
    attribute.frame = CGRect(x: 0, y: 0, width: self.collectionView!.frame.size.width, height: height)
    self.itemsAttribute.append(attribute)
}

collectionView可滾動範圍添加背景圖片

4. 總結

關於collection的裝飾視圖,核心步驟:ui

  1. 建立集成自UICollectionReusableView的自定義視圖
  2. func apply(_ layoutAttributes: UICollectionViewLayoutAttributes)中補充顯示邏輯
  3. 建立自定義layout,在func prepare()中編寫裝飾視圖的佈局屬性(最爲重要,控制裝飾視圖的顯示的位置及尺寸)

5.代碼地址

小小個子大個頭代理

相關文章
相關標籤/搜索