• iOS7之定制View Controller切换效果


    在iOS5和iOS6前,View Controller的切换主要有4种: 
    • 1. Push/Pop,NavigationViewController常干的事儿
    • 2. Tab,TabViewController点击
    • 3. Present Modal,调用ViewController的presentViewController:animated:completion:方法
    • 4. Add ChildViewController,调用- (void)addChildViewController:(UIViewController *)childController方法


    在使用Add ChildViewController的方式时,一般使用transitionFromViewController:toViewController:…的Animation block中可以实现一些简单的切换效果,这样做有2大不足: 
    • 1. 代码高度耦合,VC切换部分的代码直接写在container中,难以分离重用;
    • 2. 支持的切换效果比较有限,因为其只能使用UIView动画来切换,管理起来也略显麻烦


    于是,苹果在iOS7中引入了一些新的API来帮助开发者更容易,更松耦合地定义ViewController的转换效果。 

    知识点 


    用法 
    从上面的知识点图中可以看出,新的API主要提供了2种VC切换的方式,一种是动画式切换,即定义一种从一个VC到另一个VC的动画效果,切换的时候自动播放,第二种是交互式切换,这种方式同样需要定义动画效果,只是这个动画效果会根据跟随交互式手势来切换VC并同时播放动画效果。 这两种方式的用法略有不同。 

    动画式切换 
    • 首先定义一个动画类实现接口UIViewControllerAnimatedTransitioning, 实现接口的2个方法,一个是动画效果的时间,一个是动画效果(- (void)animateTransition:(id )transitionContext ),实现动画效果时可以从参数transitionContext中获取到切换时的上下文信息,比方说从哪个VC切换到哪个VC等。
    • 在需切换的VC中实现UIViewControllerTransitioningDelegate,并实现animationController*方法,返回一个步骤1定义的动画变量。
    • 调用展现VC切换方法,presentViewController等。


    交互式切换 
    • 定义一个类实现接口UIViewControllerInteractiveTransitioning,iOS7提供了一个默认的基于百分比的动画实现UIPercentDrivenInteractiveTransition,大家不想太麻烦可以直接扩展这个类。该类需要绑定需要实现手势控制的VC,同时把手势操作添加到该VC上,然后在处理手势动作的时候,调用接口中的方法去更新当前的动画进度。
    • 定以切换时的动画效果类。和动画式切换的方式一致
    • 在需切换的VC中实现UIViewControllerTransitioningDelegate,实现interactiveController方法,返回步骤1定义的类,实现animationController方法返回步骤2定义的动画效果。


    实战 
    下图是我实现的一个VC切换的效果图,(注:App图片是网上随便找的,不代表个人喜好:) 
     

    实现代码: 
    VC跳入动画的代码: 
    Object-c代码  收藏代码
    1. -(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext  
    2. {  
    3.     return 0.5f;  
    4. }  
    5.   
    6. -(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext  
    7. {  
    8.   
    9.     //Create the differents 3D animations  
    10.     CATransform3D viewFromTransform;  
    11.     CATransform3D viewToTransform;  
    12.       
    13.     UIView *generalContentView = [transitionContext containerView];  
    14.     UIView *fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;  
    15.     UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;  
    16.   
    17.       
    18.     viewFromTransform = CATransform3DMakeRotation(ROTATION_ANGLE, 0.0, 1.0, 0.0);  
    19.     viewToTransform = CATransform3DMakeRotation(-ROTATION_ANGLE, 0.0, 1.0, 0.0);  
    20.     [toView.layer setAnchorPoint:CGPointMake(0, 0.5)];  
    21.     [fromView.layer setAnchorPoint:CGPointMake(1, 0.5)];  
    22.       
    23. //    [generalContentView setTransform:CGAffineTransformMakeTranslation(generalContentView.frame.size.width/2.0, 0)];  
    24.       
    25.     viewFromTransform.m34 = PERSPECTIVE;  
    26.     viewToTransform.m34 = PERSPECTIVE;  
    27.       
    28.     toView.layer.transform = viewToTransform;  
    29.       
    30.   
    31.     //Add the to- view  
    32.     [generalContentView addSubview:toView];  
    33.       
    34.     [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{  
    35.         [generalContentView setTransform:CGAffineTransformMakeTranslation(-generalContentView.frame.size.width/2.0, 0)];  
    36.           
    37.         fromView.layer.transform = viewFromTransform;  
    38.         toView.layer.transform = CATransform3DIdentity;  
    39.           
    40.     } completion:^(BOOL finished) {  
    41.           
    42.         //Set the final position of every elements transformed  
    43.         [generalContentView setTransform:CGAffineTransformIdentity];  
    44.         fromView.layer.transform = CATransform3DIdentity;  
    45.         toView.layer.transform = CATransform3DIdentity;  
    46.         [fromView.layer setAnchorPoint:CGPointMake(0.5f, 0.5f)];  
    47.         [toView.layer setAnchorPoint:CGPointMake(0.5f, 0.5f)];  
    48.           
    49.           
    50.         if ([transitionContext transitionWasCancelled]) {  
    51.             [toView removeFromSuperview];  
    52.         } else {  
    53.             [fromView removeFromSuperview];  
    54.         }  
    55.           
    56.         // inform the context of completion  
    57.         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];  
    58.           
    59.     }];  
    60. }  

    手势交互代码: 
    Object-c代码  收藏代码
    1. -(void)wireToViewController:(UIViewController *)viewController  
    2. {  
    3.     self.presentingVC = viewController;  
    4.     [self prepareGestureRecognizerInView:viewController.view];  
    5. }  
    6.   
    7. - (void)prepareGestureRecognizerInView:(UIView*)view {  
    8.     UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];  
    9.     [view addGestureRecognizer:gesture];  
    10. }  
    11.   
    12. -(CGFloat)completionSpeed  
    13. {  
    14.     return 1 - self.percentComplete;  
    15. }  
    16.   
    17. - (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer {  
    18.     CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view.superview];  
    19.     switch (gestureRecognizer.state) {  
    20.         case UIGestureRecognizerStateBegan:  
    21.             // 1. Mark the interacting flag. Used when supplying it in delegate.  
    22.             self.interacting = YES;  
    23.             [self.presentingVC dismissViewControllerAnimated:YES completion:nil];  
    24.             break;  
    25.         case UIGestureRecognizerStateChanged: {  
    26.             // 2. Calculate the percentage of guesture  
    27.             CGFloat fraction = -translation.x / 300.0;  
    28.             //Limit it between 0 and 1  
    29.             fraction = fminf(fmaxf(fraction, 0.0), 1.0);  
    30.             self.shouldComplete = (fraction > 0.5);  
    31.               
    32.             [self updateInteractiveTransition:fraction];  
    33.             break;  
    34.         }  
    35.         case UIGestureRecognizerStateEnded:  
    36.         case UIGestureRecognizerStateCancelled: {  
    37.             // 3. Gesture over. Check if the transition should happen or not  
    38.             self.interacting = NO;  
    39.             if (!self.shouldComplete || gestureRecognizer.state == UIGestureRecognizerStateCancelled) {  
    40.                 [self cancelInteractiveTransition];  
    41.             } else {  
    42.                 [self finishInteractiveTransition];  
    43.             }  
    44.             break;  
    45.         }  
    46.         default:  
    47.             break;  
    48.     }  
    49. }  

    根据手势3D切换的动画代码: 
    Object-c代码  收藏代码
    1. -(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext  
    2. {  
    3.     return 0.5f;  
    4. }  
    5.   
    6. -(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext  
    7. {  
    8.   
    9.     //Create the differents 3D animations  
    10.     CATransform3D viewFromTransform;  
    11.     CATransform3D viewToTransform;  
    12.       
    13.     UIView *generalContentView = [transitionContext containerView];  
    14.     UIView *fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;  
    15.     UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;  
    16.   
    17.       
    18.     viewFromTransform = CATransform3DMakeRotation(ROTATION_ANGLE, 0.0, 1.0, 0.0);  
    19.     viewToTransform = CATransform3DMakeRotation(-ROTATION_ANGLE, 0.0, 1.0, 0.0);  
    20.     [toView.layer setAnchorPoint:CGPointMake(0, 0.5)];  
    21.     [fromView.layer setAnchorPoint:CGPointMake(1, 0.5)];  
    22.       
    23. //    [generalContentView setTransform:CGAffineTransformMakeTranslation(generalContentView.frame.size.width/2.0, 0)];  
    24.       
    25.     viewFromTransform.m34 = PERSPECTIVE;  
    26.     viewToTransform.m34 = PERSPECTIVE;  
    27.       
    28.     toView.layer.transform = viewToTransform;  
    29.       
    30.   
    31.     //Add the to- view  
    32.     [generalContentView addSubview:toView];  
    33.       
    34.     [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{  
    35.         [generalContentView setTransform:CGAffineTransformMakeTranslation(-generalContentView.frame.size.width/2.0, 0)];  
    36.           
    37.         fromView.layer.transform = viewFromTransform;  
    38.         toView.layer.transform = CATransform3DIdentity;  
    39.           
    40.     } completion:^(BOOL finished) {  
    41.           
    42.         //Set the final position of every elements transformed  
    43.         [generalContentView setTransform:CGAffineTransformIdentity];  
    44.         fromView.layer.transform = CATransform3DIdentity;  
    45.         toView.layer.transform = CATransform3DIdentity;  
    46.         [fromView.layer setAnchorPoint:CGPointMake(0.5f, 0.5f)];  
    47.         [toView.layer setAnchorPoint:CGPointMake(0.5f, 0.5f)];  
    48.           
    49.           
    50.         if ([transitionContext transitionWasCancelled]) {  
    51.             [toView removeFromSuperview];  
    52.         } else {  
    53.             [fromView removeFromSuperview];  
    54.         }  
    55.           
    56.         // inform the context of completion  
    57.         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];  
    58.           
    59.     }];  
    60. }  


    待切换的VC的动画效果配置代码: 
    Object-c代码  收藏代码
    1. -(IBAction)changeViewController:(id)sender  
    2. {  
    3.     ToViewController *vc =[[ToViewController alloc] init];  
    4.     vc.delegate = self;  
    5.     vc.transitioningDelegate = self;  
    6.     [self.interactionAnimation wireToViewController:vc];  
    7.     [self presentViewController:vc animated:YES completion:nil];  
    8. }  
    9.   
    10. -(void) didClickedDismissButton:(ToViewController *)viewController  
    11. {  
    12.     [self dismissViewControllerAnimated:YES completion:nil];  
    13. }  
    14.   
    15. - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source  
    16. {  
    17.     return self.presentAnimation;  
    18. }  
    19.   
    20. -(id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed  
    21. {  
    22.     return self.cubeAnimation;  
    23. }  
    24.   
    25. -(id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator  
    26. {  
    27.     return self.interactionAnimation.interacting? self.interactionAnimation:nil;  
    28. }  



    整个示例的完整代码已提交到Github上:https://github.com/xianlinbox/iOS7_New/tree/master/iOS7_New/VCTransitions
     
  • 相关阅读:
    elementui中el-alert实现换行的方法
    Element-UI中el-table实现简单动态数据绑定的实现
    腾讯课堂多倍速、去除xxx正在观看
    Linux vim 常用操作
    尚硅谷《谷粒商城项目总结》
    Centos 安装 Harbor
    centos 7 安装 kubernetes
    Mac VirtualBox 没有 Host-Only 选项怎么设置?
    VirtualBox 安装 centos7
    ssh 使用 sed 替换的时候,替换的字符串有单双引号的时候怎么用
  • 原文地址:https://www.cnblogs.com/56ik/p/5133099.html
Copyright © 2020-2023  润新知