UICollectionView performBatchUpdates:动画所有部分 [英] UICollectionView performBatchUpdates: animates all sections

查看:153
本文介绍了UICollectionView performBatchUpdates:动画所有部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写自定义 UICollectionViewFlowLayout ,我注意到 initialLayoutAttributesForAppearingItemAtIndexPath:我在集合视图上调用 performBatchUpdates:completion:时,将为所有部分调用initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:。结果是所有部分都应用了动画,而不是只是新添加的部分。

I'm writing a custom UICollectionViewFlowLayout and I've noticed that initialLayoutAttributesForAppearingItemAtIndexPath: and initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath: will be called for all sections when I invoke performBatchUpdates:completion: on the collection view. The result is that all sections have the animation applied to them instead of just the newly added section.

[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的调用:完成:代替简单的更新,但是现有的部分(所有部分)都是动画的。我想出了一个检查的解决方案,以确保我正在改变的布局属性最后一部分,但它感觉很烦人。

What I've tried so far is removing the call to performBatchUpdates:completion: in lieu of simple updates, but the already existing sections (all of them) are animated in anyway. I've come up with a solution of checking to make sure that I'm changing the layout attributes of only the last section, but it feels 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);
}

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

Is this the proper way to go about animating only some sections?

推荐答案

好的,我有答案;它并不比前一个漂亮得多,但它使布局不会触及数据源,所以它更干净。

OK, I've got an answer; it's not a lot prettier than the previous one, but it keeps the layout from touching the datasource, so it's cleaner.

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

Basically, we need to override prepareForCollectionViewUpdates: and finalizeCollectionViewUpdates to keep track of the sections that we're inserting. I have a mutable set that contains NSNumber instances of the sections that we're inserting.

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

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

Next, I check to see if the index path's section is included in that set when setting the initial layout attributes for items and decoration views.

-(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 是默认值。

I'm returning nil from these methods otherwise because nil is the default value.

这有一个额外的好处,即有更好的轮换动画也是如此。

This has the added benefit of having nicer rotation animations, as well.

这篇关于UICollectionView performBatchUpdates:动画所有部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆