UICollectionViewはデータの変更をアニメーション化します


83

私のプロジェクトでは、UICollectionViewを使用してアイコンのグリッドを表示しています。

ユーザーは、異なるNSSortDescriptorを使用してコアデータからフェッチを呼び出すセグメント化されたコントロールをクリックすることで、順序を変更できます。

データの量は常に同じで、最終的には異なるセクション/行になります。

- (IBAction)sortSegmentedControlChanged:(id)sender {

   _fetchedResultsController = nil;
   _fetchedResultsController = [self newFetchResultsControllerForSort];

   NSError *error;
   if (![self.fetchedResultsController performFetch:&error]) {
       NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
   }

   [self.collectionView reloadData];
}

問題は、reloadDataが変更をアニメーション化せず、UICollectionViewが新しいデータをポップするだけであるということです。

セルが変更の前後にあったindexPathを追跡し、[self.collectionView moveItemAtIndexPath:toIndexPath:]を使用して変更のアニメーションを実行する必要がありますか、それともより良い方法がありますか?

私はcollectionViewsのサブクラス化にあまり興味がなかったので、どんな助けも素晴らしいでしょう...

ありがとう、ビル。


そのreloadData呼び出しをアニメーションブロックでラップしてみましたか?
simon 2012年

回答:


71

reloadDataはアニメーション化せず、UIViewアニメーションブロックに配置されたときに確実にアニメーション化されません。UICollecitonViewのperformBatchUpdatesブロックに入れたいので、次のようなものを試してください。

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:^(BOOL finished) {
    // do something on completion 
}];

5
はい、それは機能しているようですが、セクション番号を保存している場合に限ります...それ以外の場合は、「無効なセクション数を受け取ります。更新後のコレクションビューに含まれるセクションの数(10)は、次の数と同じである必要があります。更新前のコレクションビューに含まれるセクション(16)」。セクションを手動で挿入/削除する必要があります...とにかく受け入れられます!ありがとう。
nimrod7 2012年

1
「手動」とは、UICollectionViewのinsertSections / moveSection:toSection / deleteSections呼び出しを介することを意味しますか?または、他の何か?(申し訳ありませんが、これまでのところ、UICollectionViewの使用には静的なセクション数があります)
ストライプ

1
はい、これらの方法では...思考を実装するのは少し難しいです。更新の前後のインデックスパス、削除されたものが挿入または移動された図を覚えておく必要があります...
Nimrod7 2012

12
これは、私の1セクションコレクションビューでは機能しませんでした。エラーは発生しませんでしたが、アニメーションも発生しませんでした。代用-reloadSections:すると機能します。
paulmelnikow 2013年

9
この答えは正しくありません。私の場合、reloadDataをperformBatchUpdatesに入れるとアプリがクラッシュし、セル数が前後で同じではないと表示されます。reloadSectionsを使用すると、問題が解決しました。Appleのドキュメントには、アニメーションブロックでreloadDataを呼び出さないことも示されています
Wingzero 2015

145

ラップ-reloadDataイン-performBatchUpdates:しても、1セクションのコレクションビューがアニメーション化されるようには見えません。

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadData];
} completion:nil];

ただし、このコードは機能します。

[self.collectionView performBatchUpdates:^{
    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
} completion:nil];

9
ドキュメントからの注意:アイテムが挿入または削除されているアニメーションブロックの途中でreloaddataメソッドを呼び出さないでください。挿入と削除により、テーブルのデータが自動的に適切に更新されます。
ラファエルオリベイラ

これが正解だと思います。これは私のために働いたので。セクションが1つしかないのですが、これは正しく機能していません。
Mahesh Agrawal 2015

挿入している場合は動作しません。並べ替えアニメーションを上書きします。
Andres Canella 2016

3
アニメーションを取得するためにself.collectionView performBatchUpdates呼び出しをラップする必要がないことは注目に値しますreloadSections。実際、performBatchUpdates呼び出しによって、不注意によるちらつきやセルサイズの変更の問題が発生する場合があります。
Paul Popiel 2017年

1
または[self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; reloadSections、コレクションビューまたはテーブルビューでアニメーションを使用します。
bauerMusic 2018

67

これは、すべてのセクションのリロードをアニメーション化するために私が行ったことです。

[self.collectionView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.collectionView.numberOfSections)]];

スウィフト3

let range = Range(uncheckedBounds: (0, collectionView.numberOfSections))
let indexSet = IndexSet(integersIn: range)
collectionView.reloadSections(indexSet)


3

コレクションビュー全体をperformBatchUpdates:completion:ブロック内にリロードすると、iOS9シミュレーターでグリッチなアニメーションが実行されます。UICollectionViewCell削除したい特定のものがある場合、またはそのインデックスパスがある場合はdeleteItemsAtIndexPaths:、そのブロックを呼び出すことができます。を使用deleteItemsAtIndexPaths:することで、スムーズで素敵なアニメーションを作成します。

UICollectionViewCell* cellToDelete = /* ... */;
NSIndexPath* indexPathToDelete = /* ... */;

[self.collectionView performBatchUpdates:^{
    [self.collectionView deleteItemsAtIndexPaths:@[[self.collectionView indexPathForCell:cell]]];
    // or...
    [self.collectionView deleteItemsAtIndexPaths:@[indexPath]];
} completion:nil];

1
私の場合、クラッシュの問題を解決したことについて言及したいのですが、コレクションビューでperformUpdatesを呼び出す前に、データソース(つまりセクション/アイテム数)を更新してください。
ViruMax 2016

アニメーションは他の操作からのものです。reloadDataのアニメーションがあり、どのような状況下でもありませんでした。insertItemsは昇順で挿入され、更新後に実行されます。deleteItemsは反対です。
ジェームズブッシュ

1

ヘルプテキストには次のように書かれています。

このメソッドを呼び出して、コレクションビューのすべてのアイテムを再読み込みします。これにより、コレクションビューは現在表示されているアイテムを破棄し、それらを再表示します。効率を上げるために、コレクションビューには、表示されているセルと補足ビューのみが表示されます。リロードの結果としてコレクションデータが縮小した場合、コレクションビューはそれに応じてスクロールオフセットを調整します。アイテムが挿入または削除されるアニメーションブロックの途中でこのメソッドを呼び出さないでください。挿入と削除により、テーブルのデータが自動的に適切に更新されます。

重要なのは、「コレクションビューで現在表示されているアイテムを破棄する」ことだと思います。捨てたアイテムの動きをどのようにアニメートするのでしょうか?


正確には、そうではありません。reloadDataは、アニメーションのないデュアルオペレーションです。これは、最初に削除操作、次に挿入操作です。
ジェームズブッシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.