web-dev-qa-db-ja.com

セルサイズの変更をアニメーション化するUICollectionViewは、望ましくない動作を引き起こします

標準のUICollectionViewFlowLayoutを使用してセルの単一の垂直列を表示するUICollectionViewControllerがあります。セルがタップされたときに、セルに展開/折りたたみアニメーションを作成しようとしています。次のコードを使用してこれを実現します。

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath (NSIndexPath *)indexPath
{
    [self.feedManager setCurrentlySelectedCellIndex:indexPath.item];
    [self.collectionView performBatchUpdates:nil completion:nil];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //Return the size of each cell to draw
    CGSize cellSize = (CGSize) { .width = 320, .height = [self.feedManager heightForCellAtIndexPath:indexPath] };
    return cellSize;
}

管理オブジェクトの「selectedCellIndex」プロパティは、データモデルにheightForCellAtIndexpath内で展開または縮小されたサイズを返すように指示します。

[self.collectionView performBatchUpdates:nil completion:nil];

そうして performBatchUpdates:completiong:メソッドは、このサイズの変化をうまくアニメーション化します。しかしながら!アニメーションが発生すると、セルの拡大により、画面の下部にある部分的に見えるセルが画面外に出る場合があります。

この場合、その後このセルを折りたたむと、画面外のセルはアニメーションなしで元の位置にスナップし、他の表示されているセルはすべて必要に応じてアニメーションします。私の直感では、折りたたみアニメーションが実行されているときにセルが画面外にあり、アニメーションレンダリングプロセスに含まれていないため、これが正しい動作であると言います。私の質問は、どのようにこれが起こるのを防ぐのですか?

画面外にあるかどうかに関係なく、すべてのセルを一緒にアニメーション化することを好みます。何かご意見は?

42
Cory Breed

これはUICollectionViewFlowLayoutバグですが、回避策があります。問題は、initialLayoutAttributesForAppearingItemAtIndexPath:によって返される属性のフレームが間違っていることです。具体的には、最初の画面外の位置ではなく、画面上の最終位置のフレームがあります。このメソッドをオーバーライドして正しいフレームを返すだけです。オーバーライドの基本構造は次のようになります。

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
    UICollectionViewLayoutAttributes *pose = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
    if (<test for incorrect frame>) {
        CGRect frame = pose.frame;
        frame.Origin.y = <calculate correct frame>;
        pose.frame = frame;
    }
    return pose;
}

フレームを調整する必要があるシナリオを識別する責任があります。これには、独自の内部状態を維持することが含まれる場合があります。私はこのロジックを試したことはありませんが、大まかなテストを行い、スムーズなアニメーションを取得できました。

少し一般化すると、UICollectionViewFlowLayoutは非常にバグが多く、挿入、削除、または移動と組み合わせて画面上でアイテムを移動したり、移動したりする場合に対処する必要がある多くのコーナーケースがあります。自分のシンプルなレイアウトを簡単に展開できることがわかりました。挿入、削除、または移動を行わない場合は、UICollectionViewFlowLayoutをオーバーライドするのが最善の方法です。

さらにサポートが必要な場合はお知らせください。

[〜#〜] edit [〜#〜]

サードパーティのレイアウトに興味がある場合は、カスタムグリッドレイアウト VCollectionViewGridLayout をオープンソースにし、セルの高さをスムーズに拡大するサンプルプロジェクトを追加しました。 Expand project を実行してみてください。 Sort&Filterプロジェクト もあり、アニメーションの並べ替えとフィルタリングがあります。どちらのプロジェクトでも、フローレイアウトとグリッドレイアウトを切り替えることができるため、改善を確認できます。

27
Timothy Moose