【问题标题】:Allow A Header View for Only Certain Sections Using an iOS UICollectionView使用 iOS UICollectionView 仅允许某些部分的标题视图
【发布时间】:2014-07-17 01:00:04
【问题描述】:

下面的代码正确显示了我的标题视图,但是对于 UICollectionView 中的每个部分:

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
          viewForSupplementaryElementOfKind:(NSString *)kind
                                atIndexPath:(NSIndexPath *)indexPath {
    UICollectionReusableView * headerView =
        [collectionView 
            dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader 
                               withReuseIdentifier:@"SectionHeaderCollectionReusableView"
                                      forIndexPath:indexPath];
    switch (indexPath.section) {
        case Section_One:
            return headerView;
        case Section_Two:
            return headerView;
        case Section_Three:
            return headerView;
        case Section_Four:
            return headerView;
        case Section_Five:
            return headerView;

        default:
            return headerView;
    }
}

我想做的不是显示“Section_One”或“Section_Two”的标题视图,而是返回“nil”会导致“NSInternalInconsistencyException”:

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
          viewForSupplementaryElementOfKind:(NSString *)kind
                                atIndexPath:(NSIndexPath *)indexPath {
    UICollectionReusableView * headerView =
        [collectionView 
            dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader 
                               withReuseIdentifier:@"SectionHeaderCollectionReusableView"
                                      forIndexPath:indexPath];
    switch (indexPath.section) {
        case Section_One:
            return nil;
        case Section_Two:
            return nil;
        case Section_Three:
            return headerView;
        case Section_Four:
            return headerView;
        case Section_Five:
            return headerView;

        default:
            return nil;
    }
}

我需要做什么才能仅显示某些部分的标题视图?

【问题讨论】:

  • NSInternalInconsistencyException 提供了哪些其他详细信息?
  • *** 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'从-collectionView返回的视图:viewForSupplementaryElementOfKind:atIndexPath(UICollectionElementKindSectionHeader, {length = 2,path = 0 - 0}) 没有通过调用 -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: 或 is nil ((null))' 检索到

标签: ios objective-c uicollectionview uicollectionreusableview


【解决方案1】:

继续为每个部分返回一个标题,然后在此 UICollectionViewDelegate 函数中将部分标题的大小设置为零。

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return CGSizeZero;
    }else {
        return CGSizeMake(self.collectionView.bounds.size.width, desiredHeight);
    }
}

【讨论】:

  • 如果同一个控制器处理两个集合视图并且您不希望另一个集合视图中的标题和部分怎么办?只为两个视图返回“一些”标题似乎是一种不好的做法?
  • (我在下面添加了一个关于这个的答案。)
  • @MarkusRautopuro 这是一个特定的用例,应该在单独的问题中处理。
  • 为什么,苹果,为什么?
  • 三年前的评论...请注意,如果您的布局是UICollectionViewFlowLayout,您可以获得参考尺寸,这样您就可以将“所需尺寸”委托给情节提要并制作您的代码更多“MVC”兼容:return [(UICollectionViewFlowLayout *)collectionViewLayout headerReferenceSize];
【解决方案2】:

我有一个案例,一个 UICollectionViewController 控制两个 UICollectionViews(稍后称为集合视图 1 和 2),我想要第一个的页眉,第二个没有页眉(或页脚)。

@mwright 的回答中缺少的是,当您为 collection view 2 返回CGSizeZero 时,如下所示:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    if collectionView == self.collectionView2 {
        return CGSizeZero
    }
    return < something else >
}

... 表示 collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -&gt; UICollectionReusableView 根本不会collection view 2 调用。

这意味着您不必担心会徒劳地为第二个集合视图返回“错误”标题。

【讨论】:

    【解决方案3】:

    我注意到,当您在 XIB 中将 AutoLayout 用于可重用标头时,已接受的答案中断了

    如果您将内容与边缘隔开或将标题视图中的项目设置为静态的、不可变的大小,则该问题尤其严重。将标头大小设置为 CGSizeZero 会使我的调试器控制台变得混乱,其中包含来自 Interface Builder 的数十条警告,称它们会打破所有约束以满足委托方法中设置的要求。

    虽然这本身技术上不是一场灾难,但它仍然很脏。在 Swift 和 AutoLayout 时代,必须有一个更清洁的解决方案。此外,您永远不想在工作时将这种东西运送给客户。

    为了解决这个问题,我不只是调用referenceSizeForHeaderInSection: 并返回CGSizeZero,而是使用XIB 创建了UICollectionReusableView 的另一个子类,并将其中的视图高度设置为0

    然后,我将包含在 viewForSupplementaryElementOfKind 方法中的 switch 语句之外的变体出列。这满足了界面生成器的视觉要求! ?

    无论如何,在您进行调试时,Beats 会在控制台中打印数百个不可满足的约束警告。

    【讨论】:

    • 这是针对特定情况,您提供的标题视图不是默认值,并且可能会在单独的问题中得到更好的处理
    • 实际上@mwright 这是一个有用的答案,它应该留在这个问题上。谢谢椰子
    • 你误会了,我不是说这没有帮助,我说这与所提出的问题没有直接关系。提问者没有说明他们正在使用带有自动布局的自定义标题,在这种情况下,这将是正确的答案。
    【解决方案4】:

    **

    如果返回大小为 (0, 0) 的值,则不会添加任何标题。

    **

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    
     switch section {
     case 0:
       return CGSize(width: collectionView.bounds.width, height: 70)
     case 1:
       return CGSize(width: 0, height: 0) // NO HEADER WILL BE ADDED
     case 2:
       return CGSize(width: collectionView.bounds.width, height: 70)
     case 3:
       return CGSize(width: 0, height: 0) // NO HEADER WILL BE ADDED
     default:
       return CGSize(width: collectionView.bounds.width, height: 70)
     }
    
    }
    

    【讨论】:

      【解决方案5】:

      尝试返回一个空视图。可能是更好的方法,但这可以工作....

      【讨论】:

      • "返回 [UICollectionReusableView new];"不幸的是,导致了同样的异常。有没有其他方法可以返回一个空视图?
      • UIView *eView = [UIView alloc]initWithFrame:CGRectMake(0,0,0,0)];
      • 您必须将其设为属性才能在您的集合视图委托/数据源中使用它
      • 以这种方式将视图实例化为“viewForSupplementaryElementOfKind”中的局部变量会导致相同的异常。添加属性并分配它也会引发异常(无论是在方法中还是在 viewDidLoad 中实例化)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-07
      • 1970-01-01
      • 2020-05-23
      • 2018-12-08
      • 1970-01-01
      • 2012-05-26
      相关资源
      最近更新 更多