如何在双列布局的CollectionView顶部添加单条通栏行
实现方案
你可以根据当前使用的布局类型选择对应方案,两种常用实现方式如下:
方案1:使用系统内置区头(Supplementary Header View,适用于UICollectionViewFlowLayout或UICollectionViewCompositionalLayout)
优先推荐该方案,无需修改原有双列布局逻辑
- 步骤1:开启布局的头视图显示
如果你用的是UICollectionViewFlowLayout,保留原有双列布局配置的同时,新增头尺寸配置:
如果你用的是let layout = UICollectionViewFlowLayout() // 你原有itemSize、最小间距等双列布局配置不用修改 layout.headerReferenceSize = CGSize(width: UIScreen.main.bounds.width, height: 200) // 高度替换为你通栏图片需要的实际高度UICollectionViewCompositionalLayout,在组配置中添加头视图规则:let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(200)) let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) group.boundarySupplementaryItems = [header] - 步骤2:注册自定义头视图
新建继承自UICollectionReusableView的自定义头类,内部添加你需要显示的UIImageView,之后在控制器中注册该类:collectionView.register(MyBannerHeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "BannerHeader") - 步骤3:实现数据源方法返回头视图
实现CollectionView的区头数据源代理:func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { guard kind == UICollectionView.elementKindSectionHeader else { return UICollectionReusableView() } let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "BannerHeader", for: indexPath) as! MyBannerHeaderView // 给header内的imageView赋值图片即可 return header }
如果你的CollectionView只有1个分区,该头视图会自动固定在布局最顶部,默认占满整行宽度,不会影响原有双列cell的展示逻辑。
方案2:自定义布局调整首项尺寸(适用于完全自定义UICollectionViewLayout的场景)
如果你的双列布局是完全手写的自定义布局,可以单独调整首个item的尺寸和后续item的偏移:
// 自定义布局中重写item属性计算逻辑示例 override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { guard let attributes = super.layoutAttributesForItem(at: indexPath) else { return nil } // 单独处理第一个分区的第一个item为通栏样式 if indexPath.section == 0 && indexPath.item == 0 { attributes.size = CGSize(width: collectionView?.bounds.width ?? 0, height: 200) // 同时手动调整后续所有item的frame,整体下移通栏的高度即可 } return attributes }
该方案需要自行处理后续元素的位置偏移,维护成本更高,非特殊情况不推荐使用。
内容的提问来源于stack exchange,提问作者Newbie Swift Coder
相关产品推荐
相关产品推荐

