我有一个相当标准的网格布局,它使用了UICollectionViewFlowLayout的子类。当用户点击一个单元格时,我将后续各行中的单元格向下移动,以留出空间来显示细节视图。看起来像这样:

grid mockup

在该详细视图中,我想显示另一个具有相关数据的视图,类似于iTunes显示album details的方式。现有布局的每个部分都有标题,而我目前正在将详细信息视图放到适当的位置,手动管理框架的位置。随着旋转和细胞移动,这变得棘手。

我如何通过将其视为辅助视图来说服布局来处理细节的位置?我的控制器已正确配置为将详细信息显示为补充视图,与布局相同。

最佳答案

解决了问题。大致来说,这对我有用:

  • 创建UICollectionViewLayoutAttributes的子类,并通过覆盖layoutAttributesClass函数在布局中注册它。
  • layoutAttributesForElementsInRect:中,使用[super layoutAttributesForElementsInRect:rect];检索所有标准布局属性。
  • 将该数组复制到可变数组中,并为补充视图附加另一组属性,例如[attributesCopy addObject:[self layoutAttributesForSupplementaryViewOfKind:YourSupplementaryKind atIndexPath:indexPathForTappedCell]];
  • layoutAttributesForSupplementaryViewOfKind:atIndexPath:中,使用类似以下内容获取视图的属性YourLayoutAttributes *attributes = [YourLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];
  • 测试elementKind是否与您要生成的补充视图的类型匹配
  • 使用[self layoutAttributesForItemAtIndexPath:indexPath];检索单元格的布局属性
  • 从单元格的属性更改框架以适合补充视图
  • 将新框架分配给补充属性

  • 要注意的重要部分是,您不能跳过子类 UICollectionViewLayoutAttributes。向super(一个UICollectionViewFlowLayout实例)询问补充视图的属性(除标准页眉或页脚之外的任何内容)将返回nil。我找不到有关此行为的任何具体文档,因此我可能是错的,但是以我的经验,正是子类属性解决了我的问题。

    您的代码应如下所示:
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
    {
        NSArray *allAttributesInRect = [super layoutAttributesForElementsInRect:rect];
        NSMutableArray *attributes = NSMutableArray.array;
    
        for (UICollectionViewLayoutAttributes *cellAttributes in allAttributesInRect)
        {
            // Do things with regular cells and supplemental views
        }
    
        if (self.selectedCellPath)
        {
            UICollectionViewLayoutAttributes *detailAttributes = [self layoutAttributesForSupplementaryViewOfKind:SomeLayoutSupplimentaryDetailView atIndexPath:self.selectedCellPath];
            [attributes addObject:detailAttributes];
        }
    
        return attributes.copy;
    }
    
    
    - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
    {
        SomeLayoutAttributes *attributes = [SomeLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];
    
        if ([elementKind isEqualToString:SomeLayoutSupplimentaryDetailView])
        {
            UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
            CGRect frame = cellAttributes.frame;
    
            frame.size.width = CGRectGetWidth(self.collectionView.frame); // or whatever works for you
            attributes.frame = frame;
        }
    
        return attributes;
    }
    

    您的UICollectionViewLayoutAttributes子类不一定需要任何其他属性或函数,但是在您使用dequeueReusableSupplementaryViewOfKind:forIndexPath:检索视图之后,它是一个存储该视图特定数据以供配置使用的好地方。

    10-08 05:28