自定义转场动画其实并不难,关键在于能够明白思路,也就是操作步骤。本篇博客主要以present转场动画为例,进行分析,操作。如有错误欢迎交流。
不进行修改的话,presentViewController:animated:completion:
相信这个方法很多人都是用过,称作模态推出界面,默认都是从屏幕下方推出新的控制器.
自定义的目的就是为了修改固定的推出方式,同时加上你想要的动画.
一个关键的概念: UIViewControllerAnimatedTransitioning
控制动画的协议,需要自己实现这个. 下面来一看看代码如何进行实现. 同时可以下载Demo查看 – 如果好用 请Star 表示支持
iOS 仿YY直播心形动画 & 烟花动画
iOS 雪花动画与跑马灯
iOS POP动画实践
这篇文章又用的POP,冷漠脸.png
1 |
@interface ViewController ()<<code class="objectivec"><span class="hljs-class"><span class="hljs-title">UIViewControllerTransitioningDelegate</span></span></code><code>> |
跳转点击方法
1 2 3 4 5 6 7 8 9 10 11 |
- (void)click:(UIButton *)sender { ModelViewController *modalViewController = [ModelViewController new]; // 指定代理 modalViewController.transitioningDelegate = self; // Style = 自定义方式 modalViewController.modalPresentationStyle = UIModalPresentationCustom; [self presentViewController:modalViewController animated:YES completion:NULL]; } |
UIViewControllerTransitioningDelegate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// 修改动画的两个相关的协议方法,建议仔细查看UIViewControllerTransitioningDelegate里面的注释 -(id)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { // 推出动画 - 下面会给出代码 我参照POP动画Demo写的. return [PresentAnimator new]; } - (id)animationControllerForDismissedController:(UIViewController *)dismissed { // 退出 return [DismissAnimator new]; } // 想要实现手势控制可在这个方法中进行修改 -(id)interactionControllerForDismissal:(id)animator { } |
关键在于动画如何实现 分别进行的实现PresentAnimator,DismissAnimator的实现.
UIViewControllerAnimatedTransitioning
使用这个协议进行修改.
1 |
@interface PresentAnimator : NSObject <<code class="objectivec"><span class="hljs-class"><span class="hljs-title">UIViewControllerAnimatedTransitioning</span></span></code><code>> |
PresentAnimator.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
// 交互所用时间 - (NSTimeInterval)transitionDuration:(id )transitionContext { return 0.5f; } // 具体动画方式,上面提到的POP - (void)animateTransition:(id )transitionContext { // 这里拿到即将新推出的VC的View UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view; // 这里设置退出view具体如何设置 toView.frame = CGRectMake(0,0,SCREEN_WIDTH,SCREEN_HEIGHT); toView.center = CGPointMake(transitionContext.containerView.center.x,-transitionContext.containerView.center.y); [transitionContext.containerView addSubview:toView]; // pop动画 POPSpringAnimation *positionAnim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY]; positionAnim.toValue = @(transitionContext.containerView.center.y); positionAnim.springBounciness = 10; [positionAnim setCompletionBlock:^(POPAnimation *anim,BOOL finished) { [transitionContext completeTransition:YES]; }]; POPSpringAnimation *scaleAnim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY]; scaleAnim.springBounciness = 20; scaleAnim.fromValue = [NSValue valueWithCGPoint:CGPointMake(1.2,1.4)]; [toView.layer pop_addAnimation:positionAnim forKey:@"positionAnimation"]; [toView.layer pop_addAnimation:scaleAnim forKey:@"scaleAnimation"]; } |
DismissAnimator.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
- (NSTimeInterval)transitionDuration:(id )transitionContext { return 0.5f; } - (void)animateTransition:(id )transitionContext { // fromVC 很好理解吧?? 就是从哪个控制器推过来回到哪里去. UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; POPBasicAnimation *offscreenAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY]; offscreenAnimation.toValue = @(-fromVC.view.layer.position.y); [offscreenAnimation setCompletionBlock:^(POPAnimation *anim,BOOL finished) { [transitionContext completeTransition:YES]; }]; [fromVC.view.layer pop_addAnimation:offscreenAnimation forKey:@"offscreenAnimation"]; } |
顺便值得一提的是UINavigationController转场的动画也是可以自定义的. 通过这个UINavigationControllerDelegate
来完成
1 2 |
// 签订这个协议 self.navigationController.delegate = self; |
1 2 3 4 5 6 7 8 9 10 |
- (id) navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC { if (operation == UINavigationControllerOperationPush) { // 动画的方式不变 return [PresentAnimator new]; }else{ return nil; } } |
文章参照 WWDC 2013 Session笔记 – iOS7中的ViewController切换 @ OneV’s Den