UICollectionView
容許咱們爲每個section、cell甚至是整個collectionView添加一個裝飾視圖。這玩意怎麼說呢,就是添加了一些可複用視圖,視圖的frame能夠隨意設置,劃重點是隨意設置。git
實現裝飾視圖須要自定義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的背景添加
ide
對於上面的代碼,咱們只須要改一下裝飾視圖的佈局屬性便可佈局
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) }
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) }
關於collection的裝飾視圖,核心步驟:ui
UICollectionReusableView
的自定義視圖func apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
中補充顯示邏輯func prepare()
中編寫裝飾視圖的佈局屬性(最爲重要,控制裝飾視圖的顯示的位置及尺寸)小小個子大個頭代理