如何设置首行CollectionView水平布局、下方网格布局?方案选型求助
两种界面实现方案对比与实操指南
先看你要实现的界面效果:
方案一:TableView嵌入带CollectionView的Cell
这是iOS开发里结构化实现的常用方案,适合后续要拓展更多列表模块的场景,具体步骤:
- 自定义
TableViewCell,在Cell内部嵌入UICollectionView,给Cell设置复用标识符 - 可以让自定义Cell直接遵循
UICollectionViewDataSource、UICollectionViewDelegate协议,或者把数据源代理抛给ViewController(更推荐后者,方便统一管理所有数据) - 在ViewController的
tableView:cellForRowAt:方法里,取出复用的Cell后,给Cell内的CollectionView传对应数据数组,调用reloadData() - 记得给CollectionView设置合适的
itemSize和contentInset,保证布局和目标效果匹配 - 优势:自带复用机制,滚动流畅,后续新增模块只需加新Cell类型就行
核心代码片段:
// 自定义Cell class CollectionTableViewCell: UITableViewCell, UICollectionViewDataSource { var dataList: [String] = [] lazy var collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.itemSize = CGSize(width: 100, height: 120) layout.scrollDirection = .horizontal let cv = UICollectionView(frame: .zero, collectionViewLayout: layout) cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "CollectionCell") cv.dataSource = self return cv }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(collectionView) collectionView.frame = contentView.bounds collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight] } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return dataList.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) cell.backgroundColor = .lightGray return cell } } // ViewController中调用 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CollectionTableViewCell", for: indexPath) as! CollectionTableViewCell cell.dataList = indexPath.row == 0 ? firstGroupData : secondGroupData cell.collectionView.reloadData() return cell }
方案二:ScrollView嵌套两个CollectionView
适合界面结构简单、不会频繁拓展的场景,实现更直接:
- 在ViewController里加
UIScrollView,可以通过AutoLayout约束让系统自动计算contentSize,也可以手动设置 - 给ScrollView添加两个
UICollectionView,分别设置各自的布局、数据源和代理,用约束控制两个CollectionView的上下位置和宽度 - 注意给每个CollectionView开
isScrollEnabled = true,保证横向滚动正常,ScrollView负责纵向滚动 - 劣势:没有复用机制,后续加模块会冗余;需要手动维护布局约束,容易出现滚动冲突
关键注意点:
- 用AutoLayout时,要让两个CollectionView的顶部、底部、宽度和ScrollView的内容视图关联,再设置ScrollView的
contentLayoutGuide和frameLayoutGuide约束,让系统自动计算滚动区域 - 避免滚动冲突,确保CollectionView是横向滚动,ScrollView是纵向滚动
方案选择建议
- 如果后续可能新增更多横向滚动模块,选方案一,扩展性更强
- 如果只是固定两个模块,不想写太多自定义Cell代码,选方案二更快捷
内容的提问来源于stack exchange,提问作者NumberOne
相关产品推荐
相关产品推荐

