Swift实现:在不丢失原有Table View单元格的前提下将现有Collection View添加至Table View前两个单元格
我来帮你实现这个需求!要把两个独立配置的CollectionView分别放到UITableView的前两个单元格里,同时保留原来的商品列表单元格,咱们可以通过给TableView添加专用的容器单元格来实现,具体步骤如下:
步骤1:创建承载CollectionView的TableViewCell子类
首先,我们需要两个新的UITableViewCell子类,每个里面嵌入一个CollectionView,用来分别承载你的两个CollectionView逻辑:
第一个容器单元格(承载CollectionViewOne)
import UIKit final class CollectionContainerCellOne: UITableViewCell { @IBOutlet weak var embeddedCollectionView: UICollectionView! override func awakeFromNib() { super.awakeFromNib() // 注册对应的CollectionViewCell embeddedCollectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "itemsCollectionViewCell") } }
第二个容器单元格(承载CollectionViewTwo)
import UIKit final class CollectionContainerCellTwo: UITableViewCell { @IBOutlet weak var embeddedCollectionView: UICollectionView! override func awakeFromNib() { super.awakeFromNib() // 注册对应的CollectionViewCell embeddedCollectionView.register(SelectCollectionViewCell.self, forCellWithReuseIdentifier: "SelectCollectionViewCell") } }
注意:记得在Storyboard里给这两个新的TableViewCell设置对应的ReuseIdentifier(比如
collectionContainerCellOne和collectionContainerCellTwo),并把CollectionView的IBOutlet连接好。
步骤2:修改HomeViewController的TableView数据源逻辑
接下来,我们需要调整TableView的数据源方法,区分不同行的单元格类型:
1. 更新行数计算
原来的行数只算商品数组,现在要加上前两个CollectionView的行:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 前两行是CollectionView,后面是原有商品单元格 return itemsArray.count + 2 }
2. 动态设置行高
根据不同的行返回对应的高度:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { switch indexPath.row { case 0, 1: return 200 // 根据你的需求调整CollectionView单元格的高度 default: return 100 // 原有商品单元格的高度 } }
3. 区分不同行的单元格配置
在cellForRowAt里根据行号返回不同的单元格,并给嵌入的CollectionView设置数据源和代理:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch indexPath.row { case 0: // 第一个CollectionView容器单元格 guard let cell = tableView.dequeueReusableCell(withIdentifier: "collectionContainerCellOne", for: indexPath) as? CollectionContainerCellOne else { fatalError("无法获取CollectionContainerCellOne") } cell.embeddedCollectionView.dataSource = self cell.embeddedCollectionView.delegate = self // 给CollectionView设置tag,方便后续区分 cell.embeddedCollectionView.tag = 1001 return cell case 1: // 第二个CollectionView容器单元格 guard let cell = tableView.dequeueReusableCell(withIdentifier: "collectionContainerCellTwo", for: indexPath) as? CollectionContainerCellTwo else { fatalError("无法获取CollectionContainerCellTwo") } cell.embeddedCollectionView.dataSource = self cell.embeddedCollectionView.delegate = self cell.embeddedCollectionView.tag = 1002 return cell default: // 原有商品单元格,注意这里的index要减去2(跳过前两行) let adjustedIndex = indexPath.row - 2 guard let cell = tableView.dequeueReusableCell(withIdentifier: "shopCell", for: indexPath) as? homePageTableView else { fatalError() } cell.configureHomeShop(photo: photoArrayTV[adjustedIndex], item: itemsArray[adjustedIndex]) return cell } }
步骤3:调整CollectionView的数据源逻辑
现在需要修改CollectionView的数据源方法,通过tag来区分是哪个嵌入的CollectionView:
// MARK: - CollectionView DataSource & Delegate func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { if collectionView.tag == 1001 { // 对应第一个CollectionView return imagesArray.count } else if collectionView.tag == 1002 { // 对应第二个CollectionView return selectionArray.count } return 0 } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if collectionView.tag == 1001 { guard let cellOne = collectionView.dequeueReusableCell(withReuseIdentifier: "itemsCollectionViewCell", for: indexPath) as? CollectionViewCell else { fatalError() } cellOne.configureCollection(photo: imagesArray[imagesArray.count - indexPath.row - 1]) return cellOne } else { guard let cellTwo = collectionView.dequeueReusableCell(withReuseIdentifier: "SelectCollectionViewCell", for: indexPath) as? SelectCollectionViewCell else { fatalError() } // 这里替换成indexPath.row,避免所有单元格显示同一个内容 cellTwo.confCollectionView(selectionText: selectionArray[indexPath.row]) return cellTwo } }
小提示:原来的
selectionArray.last!会导致第二个CollectionView的所有单元格显示同一个内容,改成selectionArray[indexPath.row]才能正确遍历显示每个选项哦!
步骤4:注册新的TableViewCell
最后,在viewDidLoad里注册我们新建的两个容器单元格:
override func viewDidLoad() { super.viewDidLoad() // 注册新的CollectionView容器单元格 tableView.register(CollectionContainerCellOne.self, forCellReuseIdentifier: "collectionContainerCellOne") tableView.register(CollectionContainerCellTwo.self, forCellReuseIdentifier: "collectionContainerCellTwo") tableView.dataSource = self tableView.delegate = self }
这样修改后,你的TableView前两行就会分别显示两个CollectionView,后面继续保留原来的商品列表单元格,而且所有的配置逻辑都能正常复用~
内容的提问来源于stack exchange,提问作者Мухаммед Аралбек

