如何以编程方式启用/禁用 UICollectionView 中的部分标题?

Posted

技术标签:

【中文标题】如何以编程方式启用/禁用 UICollectionView 中的部分标题?【英文标题】:How can I enable/disable section headers in UICollectionView programmatically? 【发布时间】:2014-07-03 16:15:48 【问题描述】:

在Storyboard(复选框)中可以轻松完成,但是在代码中执行呢?

【问题讨论】:

投反对票?我错过了什么吗? 【参考方案1】:

您可以使用UICollectionViewDelegateFlowLayoutcollectionView:layout:referenceSizeForHeaderInSection: 方法并返回CGSizeMake(0,0) 或相应地设置UICollectionViewFlowLayoutheaderReferenceSize

编辑: headerReferenceSize 实际上是故事板用来显示/隐藏标题的属性。我已经从 Storyboard 文件中添加了相关行

带有部分复选框打开

 <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="xAt-Uo-bMl">
           <size key="headerReferenceSize"  /></collectionViewFlowLayout>

带部分复选框关闭

 <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="xAt-Uo-bMl">
           <size key="headerReferenceSize"  /></collectionViewFlowLayout>

编辑#2:

来自the official docs:

流布局中的每个部分都可以有自己的自定义页眉和页脚。要为视图配置页眉或页脚,您必须将页眉或页脚的大小配置为非零。您可以通过实现适当的委托方法或为 headerReferenceSize 和 footerReferenceSize 属性分配适当的值来做到这一点。如果页眉或页脚大小为 0,则对应的视图不会添加到集合视图中。

【讨论】:

我遇到的问题是我动态更改了页脚大小。我在 - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 中更改了 footerReferenceSize 并通过 [self.collectionview performBatchUpdates:^ //更改 footerReferenceSize 的布局 完成:^(BOOL 完成) ];不工作,它仍然显示collectionViewLayout返回的初始值referenceSizeForFooterInSection:(NSInteger)section 令人惊讶的是它是情节提要中的复选框,但您在代码中设置了高度。这不适合我。哦,好吧,这解决了我的问题,即在 ViewDidLoad 之后的异步方法之前,我没有为 CollectionView 设置源。这在大多数 CollectionViews 中都可以正常工作,但是带有 SupplementaryViews 的不允许这样做,所以我从情节提要中禁用了它们,然后在设置源之后设置它们。【参考方案2】:

只需将您不想显示的标题的高度更改为 0...

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section

    if (section == 0) 
        return CGSizeZero;
    else 
        return CGSizeMake(collectionView.frame.size.width,50);
    

【讨论】:

该代码甚至无法编译——返回 50;不是尺寸。【参考方案3】:

nil 和 [UIView new] 都不起作用,都会抛出相同的错误。最佳答案在How to change the UICollectionView footerview's height programatically

【讨论】:

【参考方案4】:

我在此主题上找到的所有答案都假定您使用的是 UICollectionViewFlowLayout 或其子类,您可以在其中直接修改补充视图的大小。

我认为所有这些答案都有缺点,尤其是那些建议在布局子类中修改标题大小的答案,这会导致管理您的数据的任何对象与布局本身发生不必要的耦合。此外,您必须注意标题的约束,否则如果您将视图的大小设置为零,您将收到关于破坏约束的日志消息。

适用于每个 ios 版本的解决方案,无论您使用的是流式布局还是组合式布局。

只返回一个有效的空视图。

创建UICollectionReusableView的子类

class EmptyCollectionReusableView: UICollectionReusableView 
        
    override func sizeThatFits(_ size: CGSize) -> CGSize 
        var size = super.sizeThatFits(size)
        size.height = .leastNonzeroMagnitude
        
        return size
    
    

在你的集合视图中注册它,就像你在普通的补充视图中一样

let identifier = "emptySupplementaryViewIdentifier"
collectionView.register(EmptyCollectionReusableView.self,
                     forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                     withReuseIdentifier: identifier)

每当您想“隐藏”标题时,您就可以将其出列,就像使用普通补充视图一样:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView 
    
    if shouldHideHeader 
        return collectionView.dequeueReusableSupplementaryView(ofKind: kind,
                                                               withReuseIdentifier: "emptySupplementaryViewIdentifier",
                                                               for: indexPath)
    
    // Return your normal header

使用 Diffable 数据源时,将此代码插入您的数据源对象的supplementaryViewProvider

【讨论】:

【参考方案5】:

当您根本不希望出现标题时,在委托的

viewForSupplementaryElementOfKind

return [UIView new];kind == UICollectionElementKindSectionHeader:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
   
    if (kind == UICollectionElementKindSectionHeader) 
       return [UIView new]; // Or even nil, I think it would work.
    
    ...
    return /*something else that you want to return*/ ;

【讨论】:

谢谢。但是有没有办法完全禁用标题?就像在故事板设计器中一样?在设计器中禁用标头时实际发生的情况。 我认为这只是一个参考。如果我不想要标头,我总是通过不实现数据源/委托方法来管理它,或者如果我想要实现它们。我真的不认为您可以为此设置一个实际的公共属性。 如果你不想要任何部分,你甚至可以在方法 numberOfSectionsInCollectionView 中返回 0: 1.你不能返回nil 2。我确实实现了它,因为大多数时候我想要标题。直到我需要禁用它们。我想你的解决方案会做。但我仍然对最初的问题感到好奇。 返回[UIView new] 也不起作用。它发出一个错误。

以上是关于如何以编程方式启用/禁用 UICollectionView 中的部分标题?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式禁用/启用UIBarButtonItem

如何以编程方式启用/禁用网络接口? (Windows XP)

如何以编程方式启用和禁用振动模式

如何以编程方式启用/禁用 UICollectionView 中的部分标题?

如何在 Android 中以编程方式启用禁用 GPS? [复制]

如何在android studio上以编程方式检查自动启动权限是启用还是禁用