web-dev-qa-db-ja.com

UICollectionVIew:スクロールしながらセルをアニメーション化

ユーザーがリストをスクロールするときに、UICollectionViewのアイテムをアニメートして表示したい(UICollectionViewFlowLayoutのサブクラスを使用しています)。

レイアウトマネージャーで位置を指定します。できるようにしたいのは、初期変換も指定して、適切なタイミングでアニメーションに適用することです(セルが画面に最初に表示されたとき)。効果を確認するには、iOSのGoogle Plusアプリをチェックしてください。理想的には、セルの場所に応じて異なる変換を行います。

セルが表示されたとき(willDisplayCellにあるようなUITableViewに相当するものはありません)を見つける方法を見つけられないようです。

助言がありますか?

次のスクリーンショットで、Google Plusのアニメーションを作成できます。 Example in the Google Plus App

また、iPadのiPhotoもご覧ください。彼らがUIcollectionViewを使用しているかどうかはわかりません(おそらくiOS5で機能していたため、使用していません)。

21
Marc

この効果は、カスタムレイアウトとは無関係に実現できます。

アニメーションコードはcollectionView:cellForItemAtIndexPath:

セルがデキューされると、そのframeはレイアウトで指定されたものに設定されます。セルの最後のframeとして一時変数に保存できます。次に、cell.frameを画面の外側の初期位置に移動し、目的の最終位置に向かってアニメーション化します。以下に沿ったもの:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

    CGRect finalCellFrame = cell.frame;
    //check the scrolling direction to verify from which side of the screen the cell should come.
    CGPoint translation = [collectionView.panGestureRecognizer translationInView:collectionView.superview];
    if (translation.x > 0) {
        cell.frame = CGRectMake(finalCellFrame.Origin.x - 1000, - 500.0f, 0, 0);
    } else {
        cell.frame = CGRectMake(finalCellFrame.Origin.x + 1000, - 500.0f, 0, 0);
    }

    [UIView animateWithDuration:0.5f animations:^(void){
        cell.frame = finalCellFrame;
    }];

    return cell;
}

上記のコードは、スクロール方向に応じて、画面の上部から、またはどちらの側からも、水平UICollectionViewのセルをアニメーション化します。また、現在のindexPathをチェックして、セルをより複雑なレイアウトのさまざまな位置からアニメーション化したり、他のプロパティをフレームとともにアニメーション化したり、変換を適用したりすることもできます。

36
Cezar

コレクションビューのレイアウトでinitialLayoutAttributesForAppearingItemAtIndexPath:をオーバーライドする必要があります。ここでは、セルが表示された後に実際の属性にアニメーション化されるレイアウト属性アイテム(変換を含む)に任意の属性を設定できます。

標準のレイアウト属性オブジェクトで十分なオプションが提供されない場合は、オブジェクトをサブクラス化して属性を追加し、セルでapplyLayoutAttributes:をオーバーライドして、追加のプロパティを取得できます。

これは、セルをコレクションビューに追加する場合にのみ機能します。

コレクションビューを下にスクロールして変換をセルに適用するには、セル(cellForItem...にある)に直接適用するか、レイアウト属性(initialTransformと呼ばれるプロパティ)に適用することを検討します。レイアウト属性をセルに適用するときは、initialTransformを確認して適用し、アイデンティティに設定してから、アニメーションをトリガーしてアイデンティティ変換に移動します。これにより、セルがセルに最初にスクロールされたときにのみ適用されます画面。私はこれのようなものを何も実装していません、それは私がそれをどのように行うかについての単なる推測です。

5
jrturton

マークがコメントで述べたように、彼はスクロールビューを使用することになったので、標準のテーブルビューでそれを行う方法を示したいと思います。これはgoogle +で見られるのと同じ効果ではありませんが、簡単に適応できます。

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    static CGFloat duration = .5;
    static NSUInteger xOffset = 50;
    static NSUInteger yOffset = 200;
    if(scrollDirection == STAScrollDirectionDown && lastAnimatedIndex < indexPath.row)
    {
        cell.frame = CGRectMake(cell.frame.Origin.x - xOffset, cell.frame.Origin.y+yOffset, cell.frame.size.width, cell.frame.size.height);
        [UIView animateWithDuration:duration
                         animations:^{
            cell.frame = CGRectMake(cell.frame.Origin.x + xOffset, cell.frame.Origin.y - yOffset, cell.frame.size.width, cell.frame.size.height);
        } completion:^(BOOL finished) {
            lastAnimatedIndex = indexPath.row;
        }];
    }
}

セルが表示される直前に、各セルにオフセット(および場合によっては回転)を割り当ててから、アニメーションを元の設定に戻します。


もう少しエキサイティングな例:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    CATransform3D rotation = CATransform3DMakeRotation( (90.0*M_PI)/180, .0, 0.5, 0.5);
    cell.contentView.alpha = 0.8;
    cell.contentView.layer.transform = rotation;
    cell.contentView.layer.anchorPoint = CGPointMake(0, 0.5);

    [UIView animateWithDuration:.5
                     animations:^{
                         cell.contentView.layer.transform = CATransform3DIdentity;
                         cell.contentView.alpha = 1;
                         cell.contentView.layer.shadowOffset = CGSizeMake(0, 0);
                     } completion:^(BOOL finished) {
                     }];
}
3
vikingosegundo