6. UICollectionView Decoration View
UICollectionView
允许我们为每一个section、cell甚至是整个collectionView添加一个装饰视图。这玩意怎么说呢,就是添加了一些可复用视图,视图的frame可以随意设置,划重点是随意设置。
1.给section添加一张背景图片
实现装饰视图需要自定义layout,这里选择集成UICollectionViewFlowLayout
,为了省去cell的布局实现
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)
,在这里我们将对视图中的子视图设置数据。
到此就完成了一个section的背景添加
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)
}
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)
}
4. 总结
关于collection的装饰视图,核心步骤:
- 创建集成自
UICollectionReusableView
的自定义视图 - 在
func apply(_ layoutAttributes: UICollectionViewLayoutAttributes)
中补充显示逻辑 - 创建自定义layout,在
func prepare()
中编写装饰视图的布局属性(最为重要,控制装饰视图的显示的位置及尺寸)
5.代码地址
文章来源: 博客园
- 还没有人评论,欢迎说说您的想法!