UITableView嵌套UICollectionView选中状态切换代码实现咨询
解决UICollectionView单选选中状态问题(初始选中第一个+点击切换单选)
原代码存在两个核心问题:
CategoryCollectionViewCell的选中样式仅在awakeFromNib时初始化一次,后续状态变化不会自动更新UI- 未维护全局选中索引,点击新单元格时无法取消之前选中项的状态,也未实现初始选中第一个单元格的逻辑
以下是具体修改方案:
一、修改CategoryCollectionViewCell,实现状态变化自动更新UI
将样式更新逻辑抽为独立方法,通过重写isSelected属性监听状态变化,确保UI随选中状态实时更新:
class CategoryCollectionViewCell: UICollectionViewCell { override func awakeFromNib() { super.awakeFromNib() // 初始化时设置初始样式 updateSelectedStyle() } // 重写isSelected属性,状态变化时同步更新按钮状态与UI override var isSelected: Bool { didSet { containerButton.isSelected = isSelected updateSelectedStyle() } } // 抽离选中样式更新逻辑 private func updateSelectedStyle() { if containerButton.isSelected { titleLabel.textColor = .white containerButton.backgroundColor = .black } else { titleLabel.textColor = .black containerButton.backgroundColor = .white } } }
二、修改CategoryTableViewCell,实现单选逻辑与初始选中
添加变量记录当前选中索引,初始化时选中第一个单元格,点击新单元格时取消之前选中项的状态:
class CategoryTableViewCell: UITableViewCell { let categoryList = ["All", "Question", "Community"] // 记录当前选中的索引,默认初始选中第0项 private var selectedIndex: Int = 0 override func awakeFromNib() { super.awakeFromNib() set(categoryList) } func set(_ dataList: [String]) { Observable.of(dataList).bind(to: collectionView.rx.items(cellIdentifier: "CategoryCollectionViewCell", cellType: CategoryCollectionViewCell.self)) { _, data, cell in cell.titleLabel.text = data } .disposed(by: disposeBag) // 异步执行初始选中,确保collectionView已完成布局 DispatchQueue.main.async { [weak self] in guard let self = self, !dataList.isEmpty else { return } let initialIndexPath = IndexPath(item: 0, section: 0) self.collectionView.selectItem(at: initialIndexPath, animated: false, scrollPosition: .left) } collectionView.rx.itemSelected .subscribe(onNext: { [weak self] indexPath in guard let self = self else { return } // 取消之前选中的单元格状态 if self.selectedIndex != indexPath.item { let previousIndexPath = IndexPath(item: self.selectedIndex, section: 0) if let previousCell = self.collectionView.cellForItem(at: previousIndexPath) as? CategoryCollectionViewCell { previousCell.isSelected = false } } // 更新当前选中状态与索引 let currentCell = self.collectionView.cellForItem(at: indexPath) as? CategoryCollectionViewCell currentCell?.isSelected = true self.selectedIndex = indexPath.item }) .disposed(by: disposeBag) collectionView.rx.setDelegate(self) .disposed(by: disposeBag) } }
补充说明
- 使用UICollectionView自带的
selectItem(at:animated:scrollPosition:)处理初始选中,比直接修改单元格状态更符合组件规范 - 重写单元格
isSelected属性,确保UICollectionView的选中状态与自定义按钮状态保持同步,避免状态不一致 - 通过
selectedIndex变量维护全局选中状态,严格实现单选逻辑
内容的提问来源于stack exchange,提问作者jy O
相关产品推荐
相关产品推荐

