如何过滤UICollectionView的Cell?尝试将Cell高度设为0不生效该如何解决?
问题原因
你的方案不生效有两个核心原因:
- UICollectionView的cell尺寸完全由布局对象(比如UICollectionViewFlowLayout)控制,你在
cellForItemAt方法里直接修改cell的frame会被后续布局阶段的计算结果覆盖,不会生效。 - 你的代码本身存在逻辑错误:给none cell的高度赋值时,取的是
CGSize(width: 0, height: 100).width,相当于把高度设为0,但就算写对了也会被布局覆盖。
最优解决方案:过滤数据源
这是性能最高、无布局异常的方案,直接从数据源层面移除不需要展示的项,完全不用处理隐藏cell的逻辑。
- 新增一个过滤后的数据源数组,用于存储需要展示的项
// 在ViewController类中定义 var filteredSettings: [SettingModel] = []
- 每次原始数据更新时,先过滤再刷新列表
// 示例:从CoreData取出全部数据后过滤set1为true的项 filteredSettings = CoreDataManager.shared.getAllSettings().filter { $0.set1 == true } collectionView.reloadData()
- 修改数据源代理方法,使用过滤后的数组
extension ViewController: UICollectionViewDataSource, UICollectionViewDelegate{ func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return filteredSettings.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // 这里建议把你的cell类名从data改成DataCollectionViewCell,避免和系统关键字冲突 guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as? DataCollectionViewCell else { return UICollectionViewCell() } let setting = filteredSettings[indexPath.row] // 配置cell的内容 return cell } }
替代方案:通过布局代理控制尺寸
如果你的业务场景需要保留原始indexPath的对应关系,不能修改数据源,可以通过布局代理方法设置不需要展示的cell尺寸为0。
- 实现UICollectionViewDelegateFlowLayout的尺寸代理方法
extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let set1 = CoreDataManager.shared.getSetting(idx: indexPath.row).set1 if set1 { // 返回正常cell的尺寸,根据你的业务调整 return CGSize(width: 100, height: 100) } else { return .zero } } }
注意:如果使用该方案,布局设置的行间距、item间距仍会生效,可能会出现多余空白,优先推荐使用过滤数据源的方案。
内容的提问来源于stack exchange,提问作者71873
相关产品推荐
相关产品推荐

