10

をサブクラス化する基本的なコレクション ビュー レイアウトを作成していますUICollectionViewFlowLayout。ただし、いくつかの装飾ビューが重なり合っているように見えることに気付きました。

ユーザーが最後のセクションでアイテムを選択するたびに、以下のコードで新しいセクションを追加しています。このコードを実行するたびに、既存の各セクションに装飾ビューのコピーが 1 つ追加されるようです。

[collectionView performBatchUpdates:^{
    currentModelArrayIndex++;
    [collectionView insertSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex]];
    [collectionView reloadSections:[NSIndexSet indexSetWithIndex:currentModelArrayIndex-1]];
} completion:^(BOOL finished) {
    [collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:currentModelArrayIndex] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
}];

alpha装飾ビューにof0.2fを付けて、それらが積み重なるのを確認することで、これを裏付けました。

ここに画像の説明を入力

また、コレクション ビュー階層のダンプを実行したところ、 AFDecorationView4 つしか表示されないはずのインスタンスが 10 個見つかりました。

   | <AFDecorationView: 0x719ee50; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); alpha = 0; hidden = YES; layer = <CALayer: 0x719eec0>>
   | <AFDecorationView: 0x71ad980; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); alpha = 0; hidden = YES; layer = <CALayer: 0x71adb60>>
   | <AFDecorationView: 0x71afc90; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0x71afd60>>
   | <AFDecorationView: 0xd79ac30; baseClass = UICollectionReusableView; frame = (0 596.406; 768 203.281); alpha = 0; hidden = YES; layer = <CALayer: 0xd79ad00>>
   | <AFDecorationView: 0xd79cf20; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); layer = <CALayer: 0xd79cff0>>
   | <AFDecorationView: 0xd79dac0; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0xd79a980>>
   | <AFDecorationView: 0xd794fd0; baseClass = UICollectionReusableView; frame = (0 859.688; 768 225.938); layer = <CALayer: 0xd7950a0>>
   | <AFDecorationView: 0xd7a1300; baseClass = UICollectionReusableView; frame = (0 596.406; 768 203.281); layer = <CALayer: 0xd7a13d0>></CALayer:>
   | <AFDecorationView: 0xd7a35d0; baseClass = UICollectionReusableView; frame = (0 65; 768 208.125); layer = <CALayer: 0xd794470>>
   | <AFDecorationView: 0xd7a43e0; baseClass = UICollectionReusableView; frame = (0 333.125; 768 203.281); layer = <CALayer: 0xd7a44b0>>

別のカスタム レイアウトの例を見てみましたが、装飾ビューのかなりの数のインスタンスもインスタンス化されているようです。これは のバグUICollecionViewでしょうか? それとも、装飾ビュー レイアウト属性をlayoutAttributesForElementsInRect:セクションごとに 1 回だけ追加するのは私たちの責任ですか?

カスタムレイアウトの装飾関連部分は以下のような感じです。

@implementation AFCollectionViewFlowLayout

-(id)init
{
    if (!(self = [super init])) return nil;

    [self registerClass:[AFDecorationView class] forDecorationViewOfKind:AFCollectionViewFlowLayoutBackgroundDecoration];

    return self;
}

#pragma mark - Private Helper Methods

-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)attributes
{
    //implemented
}

#pragma mark - Overridden Methods

#pragma mark Cell Layout

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *attributesArray = [super layoutAttributesForElementsInRect:rect];

    NSMutableArray *newAttributesArray = [NSMutableArray array];

    for (UICollectionViewLayoutAttributes *attributes in attributesArray)
    {
        [self applyLayoutAttributes:attributes];

        if (attributes.indexPath.item == 0)
        {
            UICollectionViewLayoutAttributes *newAttributes = [self layoutAttributesForDecorationViewOfKind:AFCollectionViewFlowLayoutBackgroundDecoration atIndexPath:attributes.indexPath];

            [newAttributesArray addObject:newAttributes];
        }
    }

    attributesArray = [attributesArray arrayByAddingObjectsFromArray:newAttributesArray];

    return attributesArray;
}

#pragma mark Decoration View Layout

-(UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];

    if ([decorationViewKind isEqualToString:AFCollectionViewFlowLayoutBackgroundDecoration])
    {
        UICollectionViewLayoutAttributes *tallestCellAttributes;
        NSInteger numberOfCellsInSection = [self.collectionView numberOfItemsInSection:indexPath.section];

        for (NSInteger i = 0; i < numberOfCellsInSection; i++)
        {
            NSIndexPath *cellIndexPath = [NSIndexPath indexPathForItem:i inSection:indexPath.section];

            UICollectionViewLayoutAttributes *cellAttribtes = [self layoutAttributesForItemAtIndexPath:cellIndexPath];

            if (CGRectGetHeight(cellAttribtes.frame) > CGRectGetHeight(tallestCellAttributes.frame))
            {
                tallestCellAttributes = cellAttribtes;
            }
        }

        CGFloat decorationViewHeight = CGRectGetHeight(tallestCellAttributes.frame) + self.headerReferenceSize.height;

        layoutAttributes.size = CGSizeMake([self collectionViewContentSize].width, decorationViewHeight);
        layoutAttributes.center = CGPointMake([self collectionViewContentSize].width / 2.0f, tallestCellAttributes.center.y);
        layoutAttributes.zIndex = -1;
    }

    return layoutAttributes;
}

@end

セクションごとに 1 つの装飾ビューのみが必要なので、最初のセクションに装飾ビューを追加します。

4

2 に答える 2

3

これはのバグのようUICollectionViewです。Appleにバグレポートを提出しました。

于 2013-01-14T02:24:49.670 に答える
1

同様の問題がありましたprepareLayoutが、カスタムレイアウトクラスのすべての装飾ビューを手動で削除することで解決できました(呼び出す直前に行います[super prepareLayout]):

    // Iterate over all subviews to remove all decoration views 
    for (UIView *view in self.collectionView.subviews) 
    {
        if ([view isKindOfClass:[DecorationView class]])
        {
            [view removeFromSuperview];
        }

    }
    [super prepareLayout];
于 2013-10-17T13:24:09.013 に答える