这是我第一次实现UICollectionViewCompositionalLayout
,我不知道如何在这里实现一个伸缩头。现在我刚刚修改了dataSource.supplementaryViewProvider
函数,以包括我的自定义HeaderView,但我不知道如何使它附加到顶部。我确实找到了一些其他类型的collectionView布局的代码,但那些不适用于UICollectionViewCompositionalLayout
。对于其他布局,我发现我需要覆盖这个override func layoutAttributesForElements(in rect: CGRect)
,但是在哪里,怎么覆盖?我想从头开始知道一个方法。下面是我的方法,它根本不适用于UICollectionViewCompositionalLayout
。这是我如何创建我的头:
class StretchyCollectionHeaderView: UICollectionReusableView {
static let reuseIdentifier = "stretchyCollectionHeaderView-reuse-identifier"
let imageView: UIImageView = {
let iv = UIImageView(image: UIImage(named: "HeaderHomePage"))
iv.contentMode = .scaleAspectFill
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
// custom code for layout
backgroundColor = .red
addSubview(imageView)
imageView.fillSuperview()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我使用UICollectionReusableView
而不是UIView
,因为所有的节标题都是以UICollectionReusableView
的形式传递的。我使用了一个扩展,它将连接imageView的底部和标题视图,对于其他约束,我没有包括它,因为我认为它甚至没有使用,我将在解释结束时回来。
这是我的CollectionViewLayout的布局,标题可伸缩:
class StretchyHeaderLayout: UICollectionViewCompositionalLayout {
// we want to modify the attributes of our header component somehow
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let layoutAttributes = super.layoutAttributesForElements(in: rect)
layoutAttributes?.forEach({ (attributes) in
if attributes.representedElementKind == UICollectionView.elementKindSectionHeader && attributes.indexPath.section == 0 {
guard let collectionView = collectionView else { return }
let contentOffsetY = collectionView.contentOffset.y
print(contentOffsetY)
if contentOffsetY > 0 {
return
}
let width = collectionView.frame.width
let height = attributes.frame.height - contentOffsetY
// header
attributes.frame = CGRect(x: 0, y: contentOffsetY, width: width, height: height)
}
})
return layoutAttributes
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
然后我简单地注册所有的单元格和补充视图。然后我设置我的collectionViewLayout像这样:
func generateLayout() -> UICollectionViewLayout {
let layout = StretchyHeaderLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let isWideView = layoutEnvironment.traitCollection.horizontalSizeClass == .regular
let sectionLayoutKind = Section.allCases[sectionIndex]
switch (sectionLayoutKind) {
case .locationTab: return self.generateLocationLayout(isWide: isWideView)
case .selectCategory: return self.generateCategoriesLayout()
case .valueAddedServices: return self.generatValueAddedServicesLayout(isWide: isWideView)
}
}
return layout
}
我设置layout = StretchyHeaderLayout
,因为这是唯一可能的方式,我可以想到添加拉伸标题布局。
最后这是我如何设置我的部分标题:
dataSource.supplementaryViewProvider = { (
collectionView: UICollectionView,
kind: String,
indexPath: IndexPath) -> UICollectionReusableView? in
if indexPath.section == 0 {
guard let supplementaryView = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: StretchyCollectionHeaderView.reuseIdentifier,
for: indexPath) as? StretchyCollectionHeaderView else { fatalError("Cannot create header view") }
supplementaryView.imageView.image = UIImage(named: "HeaderHomePage")
return supplementaryView
}
else {
guard let supplementaryView = collectionView.dequeueReusableSupplementaryView(
ofKind: kind,
withReuseIdentifier: HeaderView.reuseIdentifier,
for: indexPath) as? HeaderView else { fatalError("Cannot create header view") }
supplementaryView.label.text = Section.allCases[indexPath.section].rawValue
return supplementaryView
}
}
这里我只是使用StretchyCollectionHeaderView
为第一部分和其他我使用另一个HeaderView
,其中只包含一个标签。
我认为发生的事情是因为上面的函数,它只是设置标题视图与StreatchyCollectionHeaderView
的第一部分,但不访问任何代码内的StretchyHeaderLayout
,因此不坚持顶部。不像UITableView
,我们无法附加CollectionView标题,而不是添加节标题,或者在我的案例中,节标题包含第一节的图像并附加到顶部?如何正确创建UICollectionViewCompositionalLayout
的弹性页眉?
1条答案
按热度按时间rt4zxlrg1#
我通过修改
StretchyTableHeaderView
的一些代码找到了答案。在添加下面的代码之前,我将尝试简单地解释我所做的事情。因此,首先我只是简单地创建了CollectionViewReusableView
,就像为CollectionViews
创建的任何SupplementaryView一样。实际上,我只是为stretchy TableViewHeader找到了这段代码。我只是将它转换为UICollectionReusableView
。但是,此标题视图包含scrollViewDidScroll函数,该函数操作containerView和imageView的底部约束,还操作imageView的高度,使其随滚动视图。然后你只需将它注册到你的
collectionView
中,将它作为supplementaryView
传递给First Section,并在创建布局时给予它一个高度。最后在scrollViewDidScroll
的委托方法中,寻找你的补充视图,如果找到了,就在你的头中调用scrollViewDidScroll函数。这是StretchHeaderCollectionResultableView类别:
public func scrollviewDidScroll(scrollView: UIScrollView)
是您需要在主ViewController
的scrollViewDidScroll
方法中调用的函数。将以上课程注册到您的收藏夹查看:
在创建collectionView的布局时将以下内容添加到节标题:
将数据添加到标题:
添加到第一部分,最后在ViewController中调用:
如果你的标题在你开始滚动后才拉伸,也在
viewDidAppear()
中调用上述函数。