PinterestのiOSアプリUIアニメーションを再現するまでの道のりを赤裸々に話します | nanapi TechBlog より
最後に唯一わからなかったことがあるので記載させてください。Pinterestのブログに掲載されていたソースコードなんですが…
return [[CBLPinViewTransition alloc] init];
の部分だけでどうやってあのアニメーションを表現しているのかがわかりませんでした。CBLPinViewTransitionの中身が想定できる人がいたらぜひ教えて欲しいです。
Pinterestの中の人ではないので、あくまでも想像ですが……。
CBLPinViewTransition
というクラスはUIViewControllerAnimatedTransitioning
というプロトコルを実装しているはずです。
UIViewControllerAnimatedTransitioning
では
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
- animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
というメソッドを実装する必要があります(→ 参考)。
前者は単純にアニメーション実行時間を返します。
後者は実際にアニメーションの実装を行う部分です。アニメーションが開始されるタイミングでこれが呼ばれます。
この時、(id<UIViewControllerContextTransitioning>)transitionContext
という形で画面遷移のコンテキストが渡されるのですが、このコンテキストを通して、遷移元のビューコントローラならびに遷移先のビューコントローラのインスタンスにアクセスすることができます。
また、コンテキストにはコンテナビューという遷移アニメーションに利用されるビューがあり、アニメーションに一時的に必要なスナップショットをなどをこれに格納することができます。
基本的な流れとしては……
遷移元のビューコントローラからソースとなるコレクションビューのサイズと位置を取得して、遷移先のビューコントローラのビューのサイズにフィットするようにアニメーションするという形になるでしょうか。
かなりざっくりですが、
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *source = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *destination = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
UIView *snapshot = [source.view snapshotViewAfterScreenUpdates:NO];
[container addSubview:snapshot];
CGRect sourceRect = ... // 遷移元のサイズと位置を取得
CGRect destRect = ... // 遷移元から遷移先のサイズと位置を割り出す
[UIView animateWithDuration:[self transitionDuration:transitionContext]
animations:^{
// アニメーション処理
}
completion:^(BOOL finished){
[transitionContext completeTransition:YES]; // 遷移の終了を通知
// container に追加した subview は自動的に remove されるので、明示的なクリーンアップは基本的には必要ないはず
}];
}
こんな感じでしょうか。
destRect
を計算する際、sourceRect
から遷移先のビューコントローラのビューサイズを相対的に割り出すのが少しトリッキーかもしれませんが、そうでもないかな。
ご参考になれば。