还是先看效果图。
同样它的原型也是我在cocoaChina上看到的,但那位大哥是将这两个动画分别放在presentViewControl和navigationViewControl中,我的这个就是结合了一下,顺便看怎么去写试图控制器之间的过场动画。
在控制器中需要实现的协议有:
//UIViewControllerTransitioningDelegate对应presentViewController,
//UINavigationControllerDelegate对应的则是navigationViewController.
UIViewControllerTransitioningDelegate ,UINavigationControllerDelegate
我的这个是在presentViewController中,则在进入另一个视图前:
- (void)animationBtnTap {
CustomAnimationVC *vc = [CustomAnimationVC new];
vc.transitioningDelegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
而我们需要重写协议中的方法有:
-(id)animationControllerForPresentedController:(UIViewController *)presented
presentingController:(UIViewController *)presenting
sourceController:(UIViewController *)source {
modalAnimation.type = AnimationTypePresent;
return modalAnimation;
}
返回的是我自定义的animation(可以用一个继承NSObject的类ModalAnimation并实现UIViewControllerAnimatedTransitioning中方法。),而上面的方法中需要重写UIViewControllerAnimatedTransitioning中方法:
-(void)animateTransition:(id)transitionContext {
NSAssert(NO, @"animateTransition: should be handled ");
}
-(NSTimeInterval)transitionDuration:(id)transitionContext {
return 1.0;
}
以上这两种方法是必需的。
present:
- (void)animateTransition:(id)transitionContext {
if (self.type == AnimationTypePresent) {
UIView *containView = [transitionContext containerView];
UIView *modalView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
[containView addSubview:modalView];
[containView bringSubviewToFront:modalView];
modalView.frame = CGRectMake(40, containView.centerY, containView.width - 40 *2, 100);
[UIView animateWithDuration:1.0 delay:0.0 usingSpringWithDamping:0.8 initialSpringVelocity:1.0 options:0 animations:^{
modalView.frame = CGRectMake(0, 0, containView.width, containView.height);
//modalView.center = containView.center;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
只是简单的改变frame。
else {
UIView *containerView = [transitionContext containerView];
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *fromSnapShot = [fromViewController.view snapshotViewAfterScreenUpdates:NO];
fromSnapShot.frame = fromViewController.view.frame;
[containerView insertSubview:fromSnapShot aboveSubview:fromViewController.view];
[fromViewController.view removeFromSuperview];
toViewController.view.frame = fromSnapShot.frame;
[containerView insertSubview:toViewController.view belowSubview:fromSnapShot];
CGFloat width = floorf(fromSnapShot.frame.size.width/2.0) + 5.0;
[UIView animateKeyframesWithDuration:1.3 delay:0.0 options:0 animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.2 animations:^{
CATransform3D fromAni = CATransform3DIdentity;
fromAni.m34 = 1.0 / -2000;
fromAni = CATransform3DTranslate(fromAni, 0, 0, -590);
fromSnapShot.layer.transform = fromAni;
CATransform3D toAni = CATransform3DIdentity;
toAni.m34 = 1.0 / -2000;
toAni = CATransform3DTranslate(toAni, 0, 0, -600);
toViewController.view.layer.transform = toAni;
}];
[UIView addKeyframeWithRelativeStartTime:0.2 relativeDuration:0.2 animations:^{
if (self.type == AnimationTypeDismiss) {
fromSnapShot.layer.transform = CATransform3DTranslate(fromSnapShot.layer.transform,
width, 0.0, 0);
toViewController.view.layer.transform = CATransform3DTranslate(toViewController.view.layer.transform, -width, 0.0, 0.0);
}
}];
[UIView addKeyframeWithRelativeStartTime:0.4 relativeDuration:0.2 animations:^{
fromSnapShot.layer.transform = CATransform3DTranslate(fromSnapShot.layer.transform, 0.0, 0.0, -200);
toViewController.view.layer.transform = CATransform3DTranslate(toViewController.view.layer.transform, 0, 0, 500);
}];
[UIView addKeyframeWithRelativeStartTime:0.6 relativeDuration:0.2 animations:^{
CATransform3D fromT = fromSnapShot.layer.transform;
CATransform3D toT = toViewController.view.layer.transform;
if (self.type == AnimationTypeDismiss) {
fromT = CATransform3DTranslate(fromT, floorf(-width), 0, 200);
toT = CATransform3DTranslate(toT, floorf(width * 0.03), 0, 0);
}
fromSnapShot.layer.transform = fromT;
toViewController.view.layer.transform = toT;
}];
[UIView addKeyframeWithRelativeStartTime:0.80 relativeDuration:0.20 animations:^{
toViewController.view.layer.transform = CATransform3DIdentity;
}];
} completion:^(BOOL finished) {
[_coverButton removeFromSuperview];
[fromSnapShot removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
这段代码就比较复杂,首先transitionContext上下文拿到from,to的View,然后一个帧动画,每一个帧又是一个小动画,当然每一个小动画中用到了3DAnimation,这样View不仅会在平面上移动,而且也会在z轴上移动(同时改变View的宽度)。
在第二个试图控制器中给View一个向下的滑动手势后:
- (void)presentedLastViewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
这样就完成上面的动画效果。