UICollectionView performBatchUpdates:动画所有部分

Ash*_*row 14 objective-c uikit ios6 uicollectionview uicollectionviewlayout

我正在写一个自定义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];
}];
Run Code Online (Sandbox Code Playgroud)

我到目前为止所尝试的是删除调用而performBatchUpdates:completion:不是简单的更新,但是已经存在的部分(所有部分)都是动画的.我想出了一个检查的解决方案,以确保我更改了最后一节的布局属性,但它感觉很hacky.

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

这是仅仅为某些部分制作动画的正确方法吗?

Ash*_*row 7

好的,我有一个答案; 它并不比前一个漂亮得多,但它使布局不会触及数据源,因此它更清晰.

基本上,我们需要覆盖prepareForCollectionViewUpdates:finalizeCollectionViewUpdates跟踪我们插入的部分.我有一个可变集,其中包含NSNumber我们正在插入的部分的实例.

-(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];
}
Run Code Online (Sandbox Code Playgroud)

接下来,我在设置项目和装饰视图的初始布局属性时检查索引路径的部分是否包含在该集合中.

-(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;
}
Run Code Online (Sandbox Code Playgroud)

nil从这些方法返回,否则因为nil是默认值.

这还具有更好的旋转动画的额外好处.