私のUICollectionViewでは、セルの1つにアニメーションが含まれており、セルの境界を超えてしまい、近くにある他のセルで覆われています。この特別なセルを他のセルの上に作成して、アニメーションを完璧に表現することは可能ですか?ありがとう。
2 に答える
私はこれと同じ必要がありました
具体的には、選択したコレクションビュー内のセルに基づいたモーダルビューコントローラーを提示したいと思います。ライブラリを見ていると、iBooksでこの種の動作を確認できます。コレクションから「本」を選択すると、「ポップアウト」して本が開きます。
セルを「そのまま」スケーリングするだけでは、他のセルがオーバーレイされる可能性がありますが、これは望ましくありません。
これを機能させるには、セルのスーパービュー(UICollectionViewに直接ではない場合があります!)と元の中心点を覚えているだけです。次に、それをスーパービューから削除し、メインビューに追加し(オプションで前面に表示します)、アニメーションを実行します。完了ブロックで、変換をIdentity(変換なし)にリセットし、メインビューから削除して、元の親と中心点に追加し直します。
以下にサンプルコードがありますが、いくつか注意点があります。
- 実際の実装では複数のメソッドで情報を使用するため、アニメーションの状態情報にIVARSを使用します
- 私のコードが行う追加の変換のためにQuartzCore3D変換も使用していますが、これはこの回答の範囲外です
- セルに「animating」プロパティを追加して、アニメーション中の外観を変更しました(スケールが良くなるように)
- 最後に、シーン内の次のVCを実際に起動するために実際のアプリで行った非標準のプレゼンテーションコントローラーを呼び出すのではなく、この例の最後で標準のモーダルプレゼンテーションを行うようにコードを切り替えました
おそらく他にも必要な調整がありますが、上記で概説した基本的な手法は間違いなく機能します。
// Assume: UIView *cell == cell we are animating
// Assume: UIViewController *vc == View controlelr we will launch
// Assume: IVAR CGPoint _animationCellOrigCenter
// Assume: IVAR UIView *_animationCellParent
// Assume: IVAR UIView *_animationCell;
// Save "before" state before animating:
_animationCellOrigCenter = cell.center;
_animationCellParent = cell.superview;
_animationCell = cell;
// Where is the cell currently in the main view?
CGPoint cellViewLoc = [self.view convertPoint:_animationCellOrigCenter fromView:_animationCellParent];
// OK. Hoist the cell into the main view:
[cell removeFromSuperview];
cell.center = cellViewLoc;
[self.view addSubview:cell];
[self.view bringSubviewToFront:cell];
CGSize cellSize = cell.bounds.size;
CGSize newSize = CGSizeMake(600,600); // YMMV
[cell.superview bringSubviewToFront:cell];
// Get ready to do some animating:
CGSize viewSize = collectionView.bounds.size;
CGPoint destination = CGPointMake(viewSize.width / 2, viewSize.height / 2);
CGFloat scaleX = newSize.width / cellSize.width;
CGFloat scaleY = newSize.height / cellSize.height;
cell.animating = YES;
[UIView animateWithDuration:.2
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
cell.layer.transform = CATransform3DMakeScale(scaleX, scaleY, 1);
cell.center = destination;
}
completion:^(BOOL finished) {
[self presentViewController:vc
animated:YES
completion:^{
// Put everything back the way we found it!
[_animationCell removeFromSuperview];
[_animationCellParent addSubview:_animationCell];
_animationCell.center = _animationCellOrigCenter;
_animationCell.layer.transform = CATransform3DIdentity;
_animationCell.animating = NO;
}
];
}
];
これはかなり簡単です。セルを他のセルの上に展開する前に、コレクションビューのスクロールビューに追加し、不要になったときにセルを削除します。以下では、これを行ってから、各セル自体にアニメーションを追加して、他のセルの上に展開させました。簡単にするために、そのアニメーションは省略しました。
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
let cell = collectionView.cellForItemAtIndexPath(indexPath)
self.collectionView?.addSubview(cell!)
return true
}
override func collectionView(collectionView: UICollectionView, shouldDeselectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
let cell = collectionView.cellForItemAtIndexPath(indexPath)
if (cell?.superview != nil) {
cell?.removeFromSuperview()
}
return true
}