在reloadItemsAtIndexPaths之后避免使用UICollectionView的动画

Mar*_*cin 80 animation uiview ios ios6 uicollectionview

调用reloadItemsAtIndexPaths后,UICollectionView动画项目(淡入淡出动画).

有没有办法避免这个动画?

iOS 6

Stu*_*art 205

值得注意的是,如果您的目标是iOS 7及更高版本,则可以使用新UIView方法performWithoutAnimation:.我怀疑在幕后这与其他答案(暂时禁用UIView动画/核心动画动作)的作用大致相同,但语法很好而且干净.

所以对于这个问题尤其......

Objective-C的:

[UIView performWithoutAnimation:^{
    [self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
Run Code Online (Sandbox Code Playgroud)


迅速:

UIView.performWithoutAnimation {
    self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
Run Code Online (Sandbox Code Playgroud)


当然,这个原则可以应用于您希望确保更改动画的任何情况.

  • @ user2159978这是对的; 这里的所有答案暂时禁用UIView动画.动画仅对从传入块内发起的动作禁用,在这种情况下只是集合视图的重新加载.对于被问到的问题,这是一个完全有效的答案,所以我认为它不值得投票. (10认同)
  • 在iOS 7+上,这比我接受的答案要好. (3认同)
  • 该解决方案在 iOS 14 上不再适用,在这个块中我使用 reloadData,但在 iOS 13 上它可以工作 (2认同)

Sam*_*Sam 155

你也可以试试这个:

UICollectionView *collectionView;
Run Code Online (Sandbox Code Playgroud)

...

[UIView setAnimationsEnabled:NO];

[collectionView performBatchUpdates:^{
    [collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
    [UIView setAnimationsEnabled:YES];
}];
Run Code Online (Sandbox Code Playgroud)

编辑:

我还发现,如果你包装performBatchUpdates一个UIView动画块,使用UIView动画而不是默认动画,所以你可以将动画持续时间设置为0,如下所示:

[UIView animateWithDuration:0 animations:^{
    [collectionView performBatchUpdates:^{
        [collectionView reloadItemsAtIndexPaths:indexPaths];
    } completion:nil];
}];
Run Code Online (Sandbox Code Playgroud)

如果你想在插入和删除期间使用iOS 7弹性动画,这是非常酷的!

  • 正如彼得所说,这会干扰其他动画.相反,您应该在完成块之外调用[UIView setAnimationsEnabled:YES].这样你只能防止1个动画. (5认同)
  • 谢谢,这也适用于"reloadSections:" (4认同)
  • 我添加了一种替代方法,它完全相同. (2认同)
  • 将“performBatchUpdates”包装在“animateWithDuration”内真是太棒了!谢谢你的提示! (2认同)

Mat*_* Mc 12

调用reloadItemsAtIndexPaths之后,UICollectionView会设置动画项目(淡入动画)。

有办法避免这种动画吗?

iOS 6

我假设您正在使用FlowLayout。由于您要摆脱淡入淡出的动画,请尝试以下操作:

import UIKit

class NoFadeFlowLayout: UICollectionViewFlowLayout {

    override func initialLayoutAttributesForAppearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attrs = super.initialLayoutAttributesForAppearingItem(at: itemIndexPath)
        attrs?.alpha = 1.0
        return attrs
    }

    override func finalLayoutAttributesForDisappearingItem(at itemIndexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attrs = super.finalLayoutAttributesForDisappearingItem(at: itemIndexPath)
        attrs?.alpha = 1.0
        return attrs
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个非常老的问题,因此您可能不再针对iOS 6。我亲自在tvOS 11上工作,并遇到了相同的问题,所以对于那些遇到相同问题的人来说,这就是这里。

  • 这个答案有 3 或 4 条评论,其效果是“哇,这真的很好用!” 有人决定删除评论。我认为,事实上,这是实现这一目标的现代且非 hacky 的方式,这些评论是对这一点的认可。 (2认同)

Gio*_*lla 7

在UICollectionView上写了一个类别来做到这一点.诀窍是在重新加载时禁用所有动画:

if (!animated) {
    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}

[self reloadItemsAtIndexPaths:indexPaths];

if (!animated) {
    [CATransaction commit];
}
Run Code Online (Sandbox Code Playgroud)

  • 你也可以只做 `CATransaction.setDisableActions(true)` 作为这个的简写。 (2认同)

Amj*_*asi 6

extension UICollectionView {
    func reloadWithoutAnimation(){
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
        self.reloadData()
        CATransaction.commit()
    }
}
Run Code Online (Sandbox Code Playgroud)


mar*_*cks 5

这是Swift 3版本,performBatchUpdates没有动画UICollectionView。我发现此方法对我而言要好得多,collectionView.reloadData()因为它减少了插入记录时的单元交换。

func appendCollectionView(numberOfItems count: Int){

        // calculate indexes for the items to be added
        let firstIndex = dataItems.count - count
        let lastIndex = dataItems.count - 1

        var indexPaths = [IndexPath]()
        for index in firstIndex...lastIndex {
            let indexPath = IndexPath(item: index, section: 0)
            indexPaths.append(indexPath)
        }

   UIView.performWithoutAnimation {

        self.collectionView.performBatchUpdates({ () -> Void in
            self.collectionView.insertItems(at: indexPaths)
        }, completion: { (finished) -> Void in

        })
    }
}
Run Code Online (Sandbox Code Playgroud)