玩转iOS转场动画(二)

简介: 玩转iOS转场动画

   首先我们需要实现TransDelegate类中的如下两个函数:


- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed{

   return [AniObject new];

}

- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator{

   //遵守了UIViewControllerInteractiveTransitioning协议的对象

   return self.object;

}

UIViewControllerInteractiveTransitioning协议用来处理可交互的转场动画的具体表现,需要注意,因为使用的是可交互的转场动画,UIViewControllerAnimatedTransitioning协议中的animateTransition:方法可以空实现。下面我们再创建一个遵守UIViewControllerInteractiveTransitioning协议的类,比如命名为IntObject,上面代码中的self.object即是这个类的示例,IntObject.h文件如下:


@interface IntObject : NSObject<UIViewControllerInteractiveTransitioning>


-(void)updateAniProgress:(CGFloat)progress;


-(void)finish;


-(void)cancel;


@end

IntObject.m文件实现如下:


@interface IntObject()


@property(nonatomic,strong)id<UIViewControllerContextTransitioning> context;


@end


@implementation IntObject


//这个函数用来保存transitionContext

-(void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext{

   self.context = transitionContext;

   //跳转的界面

   UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

   UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

   //最终的位置

   toVC.view.frame = [transitionContext finalFrameForViewController:toVC];

   //添加到内容视图

   [[transitionContext containerView]insertSubview:toVC.view belowSubview:fromVC.view];

}

//更新动画状态

-(void)updateAniProgress:(CGFloat)progress{

   UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

   //最终的位置

   CGRect fR = CGRectMake( [UIScreen mainScreen].bounds.size.width*progress, 0, [UIScreen mainScreen].bounds.size.width,  [UIScreen mainScreen].bounds.size.height);

   frameVC.frame = fR;

}

//结束转场

-(void)finish{

   [UIView animateWithDuration:0.2 animations:^{

       UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

       frameVC.frame = CGRectMake([UIScreen mainScreen].bounds.size.width, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);

   } completion:^(BOOL finished) {

       [self.context completeTransition:YES];

   }];

}

//取消转场

-(void)cancel{

   [UIView animateWithDuration:0.2 animations:^{

       UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

       frameVC.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);

   } completion:^(BOOL finished) {

       [self.context cancelInteractiveTransition];

   }];

}


@end

下面我们来添加手势,在ViewController2类中添加如下代码:


@interface ViewController2 ()

@property(nonatomic,strong)UIPanGestureRecognizer * pan;

@end


@implementation ViewController2


- (void)viewDidLoad {

   [super viewDidLoad];

   self.view.backgroundColor = [UIColor redColor];

   [self.view addGestureRecognizer:self.pan];

   // Do any additional setup after loading the view.

}



-(void)pan:(UIPanGestureRecognizer *)pan{


   CGPoint translatedPoint = [pan translationInView:self.view];

   CGFloat persent =  translatedPoint.x /  [[UIScreen mainScreen]bounds].size.width;

   if (persent<0) {

       return;

   }

   persent = fabs(persent);

   IntObject * obj = [(TransDelegate *)self.transitioningDelegate object];

   switch (pan.state) {

       case UIGestureRecognizerStateBegan:{

           [self dismissViewControllerAnimated:YES completion:nil];

           break;

       }

       case UIGestureRecognizerStateChanged:{

           //手势过程中,通过updateInteractiveTransition设置pop过程进行的百分比

           [obj updateAniProgress:persent];

           break;

       }

       case UIGestureRecognizerStateEnded:{

           //手势完成后结束标记并且判断移动距离是否过半,过则finishInteractiveTransition完成转场操作,否者取消转场操作

           if (persent > 0.5) {

               [obj finish];

           }else{

               [obj cancel];

           }

           break;

       }

       default:

           break;

   }

}

-(UIPanGestureRecognizer *)pan{

   if (!_pan) {

       _pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];

   }

   return _pan;

}

@end

手势效果如下:




其实,上面演示的是我们自己创建了一个类来实现UIViewControllerInteractiveTransitioning协议,其实系统也为我们提供一个类:UIPercentDrivenInteractiveTransition类,我们可以直接调用这个类的如下3个函数而不需要我们自己重写了,但是必须实现UIViewControllerAnimatedTransitioning协议中的transitionContext函数来实现动画效果。


- (void)updateInteractiveTransition:(CGFloat)percentComplete;

- (void)cancelInteractiveTransition;

- (void)finishInteractiveTransition;

其实现原理与我们上面进行完全的自定义是一样的。


三、导航转场动画的自定义


   导航转场动画的原理与模态跳转转场动画的原理基本是一致的,不同的我们需要设置UINavigationController实例的delegate为遵守UINavigationControllerDelegate协议的类对象。之后实现如下两个函数:


//设置转场的动画不论是push或pop 返回nil 则使用系统默认的导航转场动画

- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController

                                           animationControllerForOperation:(UINavigationControllerOperation)operation

                                                        fromViewController:(UIViewController *)fromVC

                                                          toViewController:(UIViewController *)toVC  {

   NSLog(@"sss");

   return nil;

}

//设置可交互的转场动画

- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController

                                  interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController{

   NSLog(@"aaa");

   return nil;

}

可以看到 animationControllerForOperation:函数依然需要返回一个遵守了UIViewControllerAnimatedTransitioning协议的对象,使用方式和前面所介绍的模态跳转自定义转场一模一样。UINavigationControllerOperation这个枚举将告知开发者导航所做的操作,如下:


typedef NS_ENUM(NSInteger, UINavigationControllerOperation) {

   UINavigationControllerOperationNone, //无

   UINavigationControllerOperationPush, //push操作

   UINavigationControllerOperationPop,  //pop操作

};

实现UIViewControllerInteractiveTransitioning协议如下:


@interface IntObject()


@property(nonatomic,strong)id<UIViewControllerContextTransitioning> context;


@end


@implementation IntObject



-(void)startInteractiveTransition:(id<UIViewControllerContextTransitioning>)transitionContext{

   self.context = transitionContext;

   //跳转的界面

   UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

   UIViewController * fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

   //最终的位置

   toVC.view.frame = [transitionContext finalFrameForViewController:toVC];

   //添加到内容视图

   [[transitionContext containerView]insertSubview:toVC.view belowSubview:fromVC.view];

}


-(void)updateAniProgress:(CGFloat)progress{

   UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

   //最终的位置

   CGRect fR = CGRectMake( [UIScreen mainScreen].bounds.size.width*progress, 0, [UIScreen mainScreen].bounds.size.width,  [UIScreen mainScreen].bounds.size.height);

   frameVC.frame = fR;

   [self.context updateInteractiveTransition:progress];

}


-(void)finish{

   [UIView animateWithDuration:0.2 animations:^{

       UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

       frameVC.frame = CGRectMake([UIScreen mainScreen].bounds.size.width, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);

   } completion:^(BOOL finished) {

     [self.context finishInteractiveTransition];

       [self.context completeTransition:YES];

   }];

}


-(void)cancel{

   [UIView animateWithDuration:0.2 animations:^{

       UIView *frameVC = [self.context viewForKey:UITransitionContextFromViewKey];

       frameVC.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);

   } completion:^(BOOL finished) {

       [self.context cancelInteractiveTransition];

       [self.context completeTransition:NO];

   }];

}


@end

如此即可以轻松实现可交互的自定义导航动画。


四、UITabBarController的转场动画


   UITabbar也可以进行转场动画的自定义,需要设置UITabBarController的delegate并实现协议中的如下两个函数:


//设置非交互的转场动画

- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController

                    animationControllerForTransitionFromViewController:(UIViewController *)fromVC

                                                      toViewController:(UIViewController *)toVC  {

}

//设置交互的转场动画

- (nullable id <UIViewControllerInteractiveTransitioning>)tabBarController:(UITabBarController *)tabBarController

                              interactionControllerForAnimationController: (id <UIViewControllerAnimatedTransitioning>)animationController{

 

}


这两个函数的应用和导航自定义动画基本是一致的,这里就不再列举代码,简单的效果见下图:

目录
相关文章
|
iOS开发
iOS 动画绘制圆形
iOS 动画绘制圆形
83 1
|
编译器 iOS开发 异构计算
读iOS核心动画笔记
读iOS核心动画笔记
55 0
|
26天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
47 1
|
2月前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
【10月更文挑战第18天】本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户按下按钮时,按钮将从圆形变为椭圆形并从蓝色渐变为绿色;释放按钮时,动画恢复原状。通过UIView的动画方法和弹簧动画效果,实现平滑自然的动画过渡。
50 5
|
3月前
|
Swift iOS开发 UED
揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【9月更文挑战第5天】本文通过具体案例介绍如何在iOS应用中使用Swift与UIKit实现自定义按钮动画,当用户点击按钮时,按钮将从圆形变为椭圆形并从蓝色渐变到绿色,释放后恢复原状。文中详细展示了代码实现过程及动画平滑过渡的技巧,帮助读者提升应用的视觉体验与特色。
63 11
|
4月前
|
Swift iOS开发 UED
【绝妙创意】颠覆你的视觉体验!揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【8月更文挑战第13天】本文通过一个具体案例,介绍如何使用Swift与UIKit在iOS应用中创建独特的按钮动画效果。当按钮被按下时,其形状从圆形变化为椭圆形,颜色则从蓝色渐变为绿色;释放后,动画反向恢复原状。利用UIView动画方法及弹簧动画效果,实现了平滑自然的过渡。通过调整参数,开发者可以进一步优化动画体验,增强应用的互动性和视觉吸引力。
53 7
|
iOS开发
iOS 常用阅读软件打开书籍的转场动画
iOS 常用阅读软件打开书籍的转场动画
94 0
|
7月前
|
iOS开发
iOS设备功能和框架: 如何使用 Core Animation 创建动画效果?
iOS设备功能和框架: 如何使用 Core Animation 创建动画效果?
138 0
|
API iOS开发
iOS 自定义转场动画 UIViewControllerTransitioning
iOS 自定义转场动画 UIViewControllerTransitioning
96 0
|
iOS开发
iOS - 个人中心果冻弹性下拉动画
iOS - 个人中心果冻弹性下拉动画
262 0
iOS - 个人中心果冻弹性下拉动画