转场动画学习中...TransitionDemo代码
实现自定义的转场动画(只涉及自定义动画,不管手势驱动)
涉及三个协议:
UIViewControllerAnimatedTransitioning(动画处理)
UIViewControllerTransitioningDelegate(页面modal时指定相关动画代理)
UINavigationControllerDelegate(页面push/pop时指定相关动画代理)
-
自定义动画类, 遵守协议UIViewControllerAnimatedTransitioning并实现相关动画(类CircleSpreadAnimation)
#pragma mark - UIViewControllerAnimatedTransitioning /** 动画时长 */ - (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{ return self.duration; } /** 动画:步骤2、4不能省 */ - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ // 1.获取ToVC UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; // 2.将ToVC's View 添加到containerView中 UIView *containerView = [transitionContext containerView]; [containerView addSubview:toVC.view]; // 3.圆形扩散动画,对ToVC's View进行动画处理 CGSize size = containerView.frame.size; CGPoint beginP = CGPointMake(size.width*0.5, size.height);//中下 switch (self.direction) { case CircleSpreadAnimationDirectionDown: beginP = CGPointMake(size.width*0.5, 0);//中上 break; case CircleSpreadAnimationDirectionRight: beginP = CGPointMake(0, size.height*0.5);//左中 break; case CircleSpreadAnimationDirectionLeft: beginP = CGPointMake(size.width, size.height*0.5);//右中 break; default: break; } UIBezierPath *beginPath = [UIBezierPath bezierPathWithArcCenter:beginP radius:1 startAngle:0 endAngle:M_PI*2 clockwise:YES]; CGFloat endX = beginP.x>size.width*0.5? beginP.x : size.width - beginP.x; CGFloat endY = beginP.y>size.height*0.5? beginP.y : size.height - beginP.y; CGFloat endRadius = sqrt(pow(endX, 2) + pow(endY, 2)); UIBezierPath *endPath = [UIBezierPath bezierPathWithArcCenter:beginP radius:endRadius startAngle:0 endAngle:M_PI*2 clockwise:YES]; CAShapeLayer *maskLayer = [CAShapeLayer layer]; maskLayer.path = endPath.CGPath; toVC.view.layer.mask = maskLayer; CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"]; animation.fromValue = (__bridge id )(beginPath.CGPath); animation.toValue = (__bridge id )(endPath.CGPath); animation.duration = self.duration; animation.delegate = self; [animation setValue:transitionContext forKey:@"transitionContext"]; [maskLayer addAnimation:animation forKey:@"pushPath"]; } -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{ id<UIViewControllerContextTransitioning> transitionContext = [anim valueForKey:@"transitionContext"]; // 4.告知完成 [transitionContext completeTransition:YES]; }
-
自定义转场动画:(相关类FromViewController、ToViewController)
-
修改转场代理(为简化,直接让FromViewController成为转场代理)
/** 从FromViewController 跳转到 ToViewController,使FromViewController成为转场代理 */
- (void)toBtnClicked{ToViewController *toVC = [[ToViewController alloc] init]; // 1.更换动画过渡代理 // self是FromViewController if (self.push) { // push时修改navigationController的代理 self.navigationController.delegate = self; [self.navigationController pushViewController:toVC animated:YES]; } else { // present时修改transitioningDelegate的代理 toVC.transitioningDelegate = self; [self presentViewController:toVC animated:YES completion:nil]; } }
实现代理,返回相关动画代理实例;
-
modal : FromViewController遵守协议
UIViewControllerTransitioningDelegate#pragma mark - UIViewControllerTransitioningDelegate // 2.modal方式:指定自定义的动画代理 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source{ // present的时候的动画代理 return self.circleAnimationUP; // nil代表使用默认过渡效果 //return nil; } - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{ // dismiss的时候的动画代理 return self.circleAnimationDown; // nil代表使用默认过渡效果 //return nil; }
-
push/pop:FromViewController遵守协议
UINavigationControllerDelegate#pragma mark - UINavigationControllerDelegate // 2.push/pop方式:指定自定义的动画代理 - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{ // 设置自定义动画 id<UIViewControllerAnimatedTransitioning> animation = nil;//使用默认效果 if (operation == UINavigationControllerOperationPush) { // push的时候的动画代理 animation = self.circleAnimationLeft; } else if (operation == UINavigationControllerOperationPop) { // pop的时候的动画代理 animation = self.circleAnimationRight; } // 3.以便在pop到当前页面的时候恢复默认转场效果 if (toVC == self) { self.navigationController.delegate = nil; } return animation; }
-
参考
WWDC 2013 Session笔记 - iOS7中的ViewController切换
几句代码快速集成自定义转场效果+ 全手势驱动