66

私がやりたいのは、UICollectionViewCellのサイズを変更し、セルが選択されたときにその変更をアニメーション化することです。セルをで選択済みとしてマークし、UICollectionViewをcollectionView: didSelectItemAtIndexPath:呼び出して、選択したセルを別のサイズで表示することで、アニメーション化せずにそれを行うことができました。reloadData

それにもかかわらず、これは一度に発生し、サイズの変化をアニメーション化する方法がわかりません。何か案は?

選択時にAnimateuicollectionviewセルをすでに見つけましたが、答えは私に固有ではなく、それが私の場合にも役立つかどうかはまだわかりませんでした。

4

10 に答える 10

89

チェイスロバーツの助けを借りて、私は今私の問題の解決策を見つけました。私のコードは基本的に次のようになります。

// Prepare for animation

[self.collectionView.collectionViewLayout invalidateLayout];
UICollectionViewCell *__weak cell = [self.collectionView cellForItemAtIndexPath:indexPath]; // Avoid retain cycles
void (^animateChangeWidth)() = ^()
{
    CGRect frame = cell.frame;
    frame.size = cell.intrinsicContentSize;
    cell.frame = frame;
};

// Animate

[UIView transitionWithView:cellToChangeSize duration:0.1f options: UIViewAnimationOptionCurveLinear animations:animateChangeWidth completion:nil];

詳細な説明:

  1. 最も重要なステップの1つは、使用invalidateLayoutしている電話UICollectionView.collectionViewLayoutです。それを忘れると、細胞がコレクションの境界を越えて成長する可能性があります。これは、おそらく起こりたくないことです。また、コードはある時点でセルの新しいサイズをレイアウトに提示する必要があることも考慮してください。私の場合(私はを使用しています)、変更されたセルの新しいサイズを反映するようにメソッドUICollectionViewFlowLayoutを調整しました。その部分を忘れて、最初に呼び出してからサイズの変更をアニメーション化しようとしてcollectionView:layout:sizeForItemAtIndexPathも、セルサイズには何も起こりません。invalidateLayout

  2. 最も奇妙な(少なくとも私にとっては)が重要なのは、アニメーションブロック内ではinvalidateLayout なく呼び出すことです。これを行うと、アニメーションはスムーズに表示されませんが、グリッチとちらつきが表示されます。

  3. コレクション全体ではなく、アニメーション化するセルであるため、コレクションビュー全体ではなく、セルを引数としてUIViewsメソッドを呼び出す必要があります。transitionWithView:duration:options:animations:completion:transitionWithView

  4. セルの方法を使用して、intrinsicContentSize必要なサイズを返しました。私の場合、セルの選択状態に応じて、セルの幅を拡大および縮小して、ボタンを表示または非表示にします。

これが何人かの人々に役立つことを願っています。私にとって、そのアニメーションを正しく機能させる方法を理解するのに数時間かかったので、私は他の人をその時間のかかる負担から解放しようとしています。

于 2012-12-08T22:58:28.957 に答える
51

セルのサイズのアニメーションは、テーブルビューの場合と同じようにコレクションビューでも機能します。セルのサイズをアニメーション化する場合は、セルの状態を反映するデータモデルを用意し(私の場合は、フラグ(CollectionViewCellExpanded、CollectionViewCellCollapsed)を使用し、それに応じてCGSizeを返します。

PerformBathUpdates呼び出しを呼び出して空にすると、ビューが自動的にアニメーション化されます。

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [collectionView performBatchUpdates:^{
        // append your data model to return a larger size for
        // cell at this index path
    } completion:^(BOOL finished) {

    }];
}
于 2013-02-11T20:29:46.577 に答える
31

-setCollectionViewLayout:animated:同じコレクションビューレイアウトの新しいインスタンスを作成するためにを使用して、変更をアニメーション化することに成功しました。

たとえば、を使用している場合は、次のようにUICollectionViewFlowLayoutなります。

// Make sure that your datasource/delegate are up-to-date first

// Then animate the layout changes
[collectionView setCollectionViewLayout:[[UICollectionViewFlowLayout alloc] init] animated:YES];
于 2013-06-16T22:44:47.197 に答える
22
[UIView transitionWithView:collectionView 
                  duration:.5 
                   options:UIViewAnimationOptionTransitionCurlUp 
                animations:^{

    //any animatable attribute here.
    cell.frame = CGRectMake(3, 14, 100, 100);

} completion:^(BOOL finished) {

    //whatever you want to do upon completion

}];

メソッド内のそれらの線に沿って何かをいじってみてくださいdidselectItemAtIndexPath

于 2012-12-08T18:03:19.730 に答える
21

これは私が見つけた最も簡単な解決策です-魅力のように機能します。スムーズなアニメーションで、レイアウトを台無しにしません。

迅速

    collectionView.performBatchUpdates({}){}

Obj-C

    [collectionView performBatchUpdates:^{ } completion:^(BOOL finished) { }];

ブロック(Swiftのクロージャ)は意図的に空のままにしておく必要があります!

于 2016-03-14T19:18:52.283 に答える
12

セルサイズをアニメーション化する良い方法は、collectionViewCell自体でisHighlightedをオーバーライドすることです。

class CollectionViewCell: UICollectionViewCell {

    override var isHighlighted: Bool {
        didSet {
            if isHighlighted {
                UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
                    self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
                }, completion: nil)
            } else {
                UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
                    self.transform = CGAffineTransform(scaleX: 1, y: 1)
                }, completion: nil)
            }
        }
    }

}
于 2017-09-05T13:24:45.350 に答える
10

PerformBatchUpdatesを使用しても、セルの内容のレイアウトはアニメーション化されません。代わりに、次を使用できます。

    collectionView.collectionViewLayout.invalidateLayout()

    UIView.animate(
        withDuration: 0.4,
        delay: 0.0,
        usingSpringWithDamping: 1.0,
        initialSpringVelocity: 0.0,
        options: UIViewAnimationOptions(),
        animations: {
            self.collectionView.layoutIfNeeded()
        },
        completion: nil
    )

これにより、非常にスムーズなアニメーションが得られます。

これはIgnatiusTremorの答えに似ていますが、トランジションアニメーションが適切に機能しませんでした。

完全なソリューションについては、https://github.com/cnoon/CollectionViewAnimationsを参照してください。

于 2017-12-14T20:38:28.200 に答える
2

これは私のために働いた。

    collectionView.performBatchUpdates({ () -> Void in
        let ctx = UICollectionViewFlowLayoutInvalidationContext()
        ctx.invalidateFlowLayoutDelegateMetrics = true
        self.collectionView!.collectionViewLayout.invalidateLayoutWithContext(ctx)
    }) { (_: Bool) -> Void in
    }
于 2015-12-02T13:36:16.780 に答える
0
class CollectionViewCell: UICollectionViewCell {
   override var isHighlighted: Bool {
       if isHighlighted {
            UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseInOut, animations: {
                self.transform = CGAffineTransform(scaleX: 0.95, y: 0.95)
            }) { (bool) in
                UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseInOut, animations: {
                    self.transform = CGAffineTransform(scaleX: 1, y: 1)
                }, completion: nil)
            }
        }
   }
}

isHighlighted変数がtrueに変更されたかどうかを確認してから、UIViewアニメーションを使用して、完了ハンドラーでアニメーション化する必要があります。

于 2019-12-30T20:26:06.290 に答える
0

信じられないかもしれませんが、これはうまくいきます

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPat`h: IndexPath) {
            
            // Make your item selected in your data source here
                    
             UIView.animate(withDuration: 0.5) {
            // call reload cells in the animation block and it'll update the selected cell's height with an animation 
                        collectionView.reloadItems(at: [indexPath])
                    }
    }

ちなみに私は自動セル高さを使用しています。(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

于 2021-11-09T22:11:52.517 に答える