14

カスタムを作成していますが、コレクションビューで呼び出すと、すべてのセクションで呼び出されることに気付きUICollectionViewFlowLayoutました。その結果、新しく追加されたセクションだけでなく、すべてのセクションにアニメーションが適用されます。initialLayoutAttributesForAppearingItemAtIndexPath:initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:performBatchUpdates:completion:

[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];
}];

これまでに試したのはperformBatchUpdates:completion:、単純な更新の代わりにへの呼び出しを削除することですが、既存のセクション(すべて)はとにかくアニメーション化されています。最後のセクションのみのレイアウト属性を変更していることを確認するための解決策を考え出しましたが、それはハックな感じがします。

if (decorationIndexPath.section == [(id<UICollectionViewDataSource>)self.collectionView.delegate numberOfSectionsInCollectionView:self.collectionView] - 1)
{
   layoutAttributes.alpha = 0.0f;
   layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);
}

これは、一部のセクションのみをアニメーション化するための適切な方法ですか?

4

1 に答える 1

7

OK、答えがあります。前のものよりもそれほどきれいではありませんが、レイアウトがデータソースに触れないようにするため、よりクリーンになります。

基本的に、挿入するセクションをオーバーライドして追跡する必要がありprepareForCollectionViewUpdates:ますfinalizeCollectionViewUpdatesNSNumber挿入するセクションのインスタンスを含む可変セットがあります。

-(void)prepareForCollectionViewUpdates:(NSArray *)updateItems
{
    [super prepareForCollectionViewUpdates:updateItems];

    [updateItems enumerateObjectsUsingBlock:^(UICollectionViewUpdateItem *updateItem, NSUInteger idx, BOOL *stop) {
        if (updateItem.updateAction == UICollectionUpdateActionInsert)
        {
            [insertedSectionSet addObject:@(updateItem.indexPathAfterUpdate.section)];
        }
    }];
}

-(void)finalizeCollectionViewUpdates
{
    [super finalizeCollectionViewUpdates];

    [insertedSectionSet removeAllObjects];
}

次に、アイテムと装飾ビューの初期レイアウト属性を設定するときに、インデックスパスのセクションがそのセットに含まれているかどうかを確認します。

-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingDecorationElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)decorationIndexPath
{
    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([elementKind isEqualToString:AFCollectionViewFlowLayoutBackgroundDecoration])
    {
        if ([insertedSectionSet containsObject:@(decorationIndexPath.section)])
        {
            layoutAttributes = [self layoutAttributesForDecorationViewOfKind:elementKind atIndexPath:decorationIndexPath];
            layoutAttributes.alpha = 0.0f;
            layoutAttributes.transform3D = CATransform3DMakeTranslation(-CGRectGetWidth(layoutAttributes.frame), 0, 0);
        }
    }

    return layoutAttributes;
}

-(UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
    UICollectionViewLayoutAttributes *layoutAttributes;

    if ([insertedSectionSet containsObject:@(itemIndexPath.section)])
    {
        layoutAttributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
        layoutAttributes.transform3D = CATransform3DMakeTranslation([self collectionViewContentSize].width, 0, 0);
    }

    return layoutAttributes;
}

それ以外の場合は、がデフォルト値nilであるため、これらのメソッドから戻ります。nil

これには、回転アニメーションがより優れているという追加の利点もあります。

于 2013-01-13T23:12:23.600 に答える