ユーザーがリストをスクロールするときに、UICollectionView
のアイテムをアニメートして表示したい(UICollectionViewFlowLayout
のサブクラスを使用しています)。
レイアウトマネージャーで位置を指定します。できるようにしたいのは、初期変換も指定して、適切なタイミングでアニメーションに適用することです(セルが画面に最初に表示されたとき)。効果を確認するには、iOSのGoogle Plusアプリをチェックしてください。理想的には、セルの場所に応じて異なる変換を行います。
セルが表示されたとき(willDisplayCell
にあるようなUITableView
に相当するものはありません)を見つける方法を見つけられないようです。
助言がありますか?
次のスクリーンショットで、Google Plusのアニメーションを作成できます。
また、iPadのiPhotoもご覧ください。彼らがUIcollectionViewを使用しているかどうかはわかりません(おそらくiOS5で機能していたため、使用していません)。
この効果は、カスタムレイアウトとは無関係に実現できます。
アニメーションコードは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
をチェックして、セルをより複雑なレイアウトのさまざまな位置からアニメーション化したり、他のプロパティをフレームとともにアニメーション化したり、変換を適用したりすることもできます。
コレクションビューのレイアウトでinitialLayoutAttributesForAppearingItemAtIndexPath:
をオーバーライドする必要があります。ここでは、セルが表示された後に実際の属性にアニメーション化されるレイアウト属性アイテム(変換を含む)に任意の属性を設定できます。
標準のレイアウト属性オブジェクトで十分なオプションが提供されない場合は、オブジェクトをサブクラス化して属性を追加し、セルでapplyLayoutAttributes:
をオーバーライドして、追加のプロパティを取得できます。
これは、セルをコレクションビューに追加する場合にのみ機能します。
コレクションビューを下にスクロールして変換をセルに適用するには、セル(cellForItem
...にある)に直接適用するか、レイアウト属性(initialTransform
と呼ばれるプロパティ)に適用することを検討します。レイアウト属性をセルに適用するときは、initialTransform
を確認して適用し、アイデンティティに設定してから、アニメーションをトリガーしてアイデンティティ変換に移動します。これにより、セルがセルに最初にスクロールされたときにのみ適用されます画面。私はこれのようなものを何も実装していません、それは私がそれをどのように行うかについての単なる推測です。
マークがコメントで述べたように、彼はスクロールビューを使用することになったので、標準のテーブルビューでそれを行う方法を示したいと思います。これは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) {
}];
}