Swift:如何选择返回集合视图部分的标题?

Posted

技术标签:

【中文标题】Swift:如何选择返回集合视图部分的标题?【英文标题】:Swift: How to Optionally return a header for a collection view section? 【发布时间】:2021-01-09 00:57:52 【问题描述】:

我有一个UICollectionViewDiffableDataSource,就像这样:

var data:UICollectionViewDiffableDataSource<Section, Message>!

我这样定义我的部分标题的布局:

let header = NSCollectionLayoutBoundarySupplementaryItem(
    layoutSize: .init(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(10)),
    elementKind: UICollectionView.elementKindSectionHeader,
    alignment: .top
)
section.boundarySupplementaryItems = [header]

最后,要返回我的标题,我有这个函数可以返回 UICollectionReusableView,如下所示:

func setupHeaderData() 
    data.supplementaryViewProvider =  collectionView, kind, indexPath in
        return DateStampBuilder(data: self.data, style: self.style).build(collectionView: collectionView, kind: kind, indexPath: indexPath)
    


太棒了:我可以在UICollectionView 中看到我的标题。

我想要什么:我怎样才能有选择地决定不显示特定部分的特定标题?

当我尝试在以下函数中返回 nil 时:

data.supplementaryViewProvider =  collectionView, kind, indexPath in

我收到以下错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the view returned from -collectionView:viewForSupplementaryElementOfKind:atIndexPath (UICollectionElementKindSectionHeader,<NSIndexPath: 0xb461f3e1dd0c21dc> length = 2, path = 0 - 0) was not retrieved by calling -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: or is nil ((null))'

我对如何“可选地”返回一个部分的标题的唯一想法是注册另一个高度为零的标题视图,并在我根本不想返回任何标题时返回此标题。

但对我来说,这似乎有点混乱,如果我在不显示标题时可以返回 nil 会更干净。

我做错了什么?


感谢您的帮助!

【问题讨论】:

【参考方案1】:

这应该在为 collectionView 创建布局时完成。这是一个关于如何使用UICollectionLayoutListConfiguration 的示例:

let sectionProvider =  [weak self] (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        var section: NSCollectionLayoutSection
        
        var listConfiguration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        
        if condition 
            listConfiguration.headerMode = .supplementary
         else 
            listConfiguration.headerMode = .none
        
        
        section = NSCollectionLayoutSection.list(using: listConfiguration, layoutEnvironment: layoutEnvironment)
        return section
    
    
let layout = UICollectionViewCompositionalLayout(sectionProvider: sectionProvider)
    
collectionView.setCollectionViewLayout(layout, animated: true)

您的条件显然可以绑定到您的数据源和部分索引,因此您不会与动态创建的部分不同步。

【讨论】:

【参考方案2】:

我最近正在研究这个问题,我想出的解决方案是根据在 supplementaryViewProvider 闭包上返回 nil 所使用的相同条件,选择性地设置组合布局 boundarySupplementaryItems

一些伪代码:

给定条件

let myCondition = ...

我的补充视图提供者:

dataSource.supplementaryViewProvider =  collectionView, kind, indexPath in 
    // ...
    guard myCondition else  return nil 

在您的组合布局提供程序函数/闭包中,您可以:

let section = NSCollectionLayoutSection(...)
if myCondition 
    let header = NSCollectionLayoutBoundarySupplementaryItem(...)
    section.boundarySupplementaryItems = [header]

这将允许您从 supplementaryViewProvider 闭包返回 nil,因为当条件为 true 时,集合视图永远不会请求补充视图(如果这样做,您仍然会看到崩溃)。

【讨论】:

【参考方案3】:

有点丑陋的解决方案,但我创建了一个简单的空视图:

class EmptyHeader : UICollectionReusableView     
    static var reuseIdentifier:String = "spacer"

然后,当我不想要标题时,我只返回此视图。 (确保先将视图注册到collectionview)。

【讨论】:

以上是关于Swift:如何选择返回集合视图部分的标题?的主要内容,如果未能解决你的问题,请参考以下文章

集合视图 - 如何在每个部分中仅选择一个单元格

如何根据swift 3中的数组选择复选标记?

独立填充集合视图的每个部分 Swift

如何在 Swift 中的集合视图上方添加水平按钮堆栈?

如何在 SWIFT 中更改 ViewController 后保留集合视图滚动位置

集合视图更新问题 - Swift