UICollectionViewは、reloadItemsAtIndexPathsが呼び出された後にアイテムをアニメーション化します(フェードアニメーション)。
このアニメーションを回避する方法はありますか?
iOS 6
回答:
iOS 7以降をターゲットにしている場合は、新しいUIView
方法を使用できることに注意してくださいperformWithoutAnimation:
。内部的には、これはここでの他の回答とほとんど同じように機能していると思います(UIView
アニメーション/コアアニメーションアクションを一時的に無効にします)が、構文は素晴らしくクリーンです。
したがって、特にこの質問については...
Objective-C:
[UIView performWithoutAnimation:^{
[self.collectionView reloadItemsAtIndexPaths:indexPaths];
}];
迅速:
UIView.performWithoutAnimation {
self.collectionView.reloadItemsAtIndexPaths(indexPaths)
}
もちろん、この原則は、変更がされていることを確認したいことをどのような状況に適用することが可能ではないアニメーション。
これを試すこともできます:
UICollectionView *collectionView;
..。
[UIView setAnimationsEnabled:NO];
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:^(BOOL finished) {
[UIView setAnimationsEnabled:YES];
}];
またperformBatchUpdates
、UIViewアニメーションブロックでラップすると、デフォルトのアニメーションの代わりにUIViewアニメーションが使用されるため、次のようにアニメーションの長さを0に設定できることもわかりました。
[UIView animateWithDuration:0 animations:^{
[collectionView performBatchUpdates:^{
[collectionView reloadItemsAtIndexPaths:indexPaths];
} completion:nil];
}];
挿入と削除の間にiOS7の弾力のあるアニメーションを使用したい場合、これは非常にクールです!
performBatchUpdates
内部はanimateWithDuration
素晴らしいです!ヒントをありがとう!
UICollectionViewは、reloadItemsAtIndexPathsが呼び出された後にアイテムをアニメーション化します(フェードアニメーション)。
このアニメーションを回避する方法はありますか?
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
}
}
これは非常に古い質問なので、おそらくiOS6をターゲットにしていないでしょう。私は個人的にtvOS11に取り組んでいて、同じ質問をしたので、これは同じ問題を抱えている人のためにここにあります。
それを行うために、UICollectionViewにカテゴリを作成しました。秘訣は、リロード中にすべてのアニメーションを無効にすることです。
if (!animated) {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
}
[self reloadItemsAtIndexPaths:indexPaths];
if (!animated) {
[CATransaction commit];
}
CATransaction.setDisableActions(true)
これの省略形として行うこともできます。
extension UICollectionView {
func reloadWithoutAnimation(){
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
self.reloadData()
CATransaction.commit()
}
}
これは、performBatchUpdates
アニメーションなしのSwift3バージョン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
})
}
}
- (void)reloadCollectionViewAnimated:(BOOL)animated {
if (animated) {
[self.collectionView performBatchUpdates:^{
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:^(BOOL finished) {
}];
} else {
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
[CATransaction commit];
}
}
$ 0.02を追加するために、選択した回答の両方のバージョンを試しましたが、元の方法の方が目的に適していました。私は、ユーザーが特定の週にカレンダーを入力し、前後にスワイプしてリストをフィルタリングするために個々の日を選択できるようにする、無限スクロールのカレンダービューに取り組んでいます。
私の実装では、古いデバイスでパフォーマンスを維持するために、カレンダービューを表す日付の配列を比較的小さく保つ必要があります。つまり、ユーザーが3週目の中央にいる状態で、約5週間分の日付を保持する必要があります。2番目のアプローチを使用する場合の問題は、アニメーションなしでコレクションビューを中央にスクロールして戻す必要がある、2番目のステップがあることです。これにより、ブロックされたベースアニメーションで、何らかの理由で非常にギザギザの外観になります。
私のコード:
[UIView setAnimationsEnabled:NO];
[self.collectionView performBatchUpdates:^{
[self.collectionView deleteItemsAtIndexPaths:indexPathDeleteArray];
[self.collectionView insertItemsAtIndexPaths:indexPathAddArray];
} completion:NULL];
[UIView setAnimationsEnabled:YES];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:14 inSection:0];
[self.collectionView scrollToItemAtIndexPath:newIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
func reloadRowsWithoutAnimation(at indexPaths: [IndexPath]) {
let contentOffset = collectionView.contentOffset
UIView.setAnimationsEnabled(false)
collectionView.performBatchUpdates {
collectionView.reloadItems(at: indexPaths)
}
UIView.setAnimationsEnabled(true)
collectionView.setContentOffset(contentOffset, animated: false)
}