侧滑的转场实现

学习了seedante大神的《iOS 视图控制器转场详解》https://github.com/seedante/iOS-Note/wiki/ViewController-Transition,觉得iOS的自定义转场功能十分强大,可以实现许多绚丽的动画效果。seedante大神的博客中代码是用的Swift语言编写的,此文中介绍的侧滑效果用ObjectiveC实现,关键性的地方有参考该文章。

在学习转场之前首先要理清楚转场中的一些关键词:

1.转场代理(Transition Delegate):自定义转场的第一步便是提供转场代理,告诉系统使用我们提供的代理而不是系统的默认代理来执行转场。有如下三种转场代理,对应上面三种类型的转场:

UINavigationControllerDelegate //UINavigationController 的 delegate 属性遵守该协议。

UITabBarControllerDelegate //UITabBarController 的 delegate 属性遵守该协议。

UIViewControllerTransitioningDelegate //UIViewController 的 transitioningDelegate 属性遵守该协议。

这里除了UIViewControllerTransitioningDelegate是 iOS 7 新增的协议,其他两种在 iOS 2 里就存在了,在 iOS 7 时扩充了这两种协议来支持自定义转场。转场发生时,UIKit 将要求转场代理将提供转场动画的核心构件:动画控制器和交互控制器(可选的);由我们实现。

2.动画控制器(Animation Controller):最重要的部分,负责添加视图以及执行动画;遵守UIViewControllerAnimatedTransitioning协议;由我们实现。

3.交互控制器(Interaction Controller):通过交互手段,通常是手势来驱动动画控制器实现的动画,使得用户能够控制整个过程;遵守UIViewControllerInteractiveTransitioning协议;系统已经打包好现成的类供我们使用。

4.转场环境(Transition Context):提供转场中需要的数据;遵守UIViewControllerContextTransitioning协议;由 UIKit 在转场开始前生成并提供给我们提交的动画控制器和交互控制器使用。

5.转场协调器(Transition Coordinator):可在转场动画发生的同时并行执行其他的动画,其作用与其说协调不如说辅助,主要在 Modal 转场和交互转场取消时使用,其他时候很少用到;遵守UIViewControllerTransitionCoordinator协议;由 UIKit 在转场时生成,UIViewController 在 iOS 7 中新增了方法transitionCoordinator()返回一个遵守该协议的对象,且该方法只在该控制器处于转场过程中才返回一个此类对象,不参与转场时返回 nil。

结合这张图:

下面是用交互转场实现的侧滑效果。

相较于一般的非交互转场,交互转场在UIViewControllerTransitioningDelegate协议里面多实现了一下两个方法:

- (nullable id )interactionControllerForPresentation:(id )animator;

-(nullable id )interactionControllerForDismissal:(id )animator;

用来返回一个UIViewControllerInteractiveTransitioning交互控制器,该类可以控制转场过程的进度,在使用中,只需返回一个UIPercentDrivenInteractiveTransition对象即可。该对象通过以下几个方法来控制转场过程的进度:

- (void)updateInteractiveTransition:(CGFloat)percentComplete;

- (void)cancelInteractiveTransition;

-(void)finishInteractiveTransition;

调用第一个成员方法需要给它一个进度的参数,告诉代理此转场应该进度一个多少,一般可以将此函数加入到手势里面调用。后面两个方法,可以直接调用,完成的结果和非交互的转场效果一样。

以下是在UIScreenEdgePanGestureRecognizer手势里面调用:

-(void)handleAction:(UIScreenEdgePanGestureRecognizer *)gesture

{

​    CGFloat translationX = [gesture translationInView:_bottomVc.view].x;

    CGFloat translationBase = _bottomVc.view.frame.size.width;

    CGFloat translationAbs = translationX > 0 ? translationX : -translationX;

    CGFloat percent = translationAbs > translationBase ? 1.0:translationAbs/translationBase;

​    if (gesture.state == UIGestureRecognizerStateBegan) {

         [_bottomVc presentViewController:self.navigation animated:YES completion:nil];

     }

       if (gesture.state == UIGestureRecognizerStateChanged) {

                     [self.interaction updateInteractiveTransition:percent];

         }

         if (gesture.state == UIGestureRecognizerStateEnded) {

        if (percent > 0.5) {

          [self.interaction finishInteractiveTransition];

         }        else

              [self.interaction cancelInteractiveTransition];

            NSLog(@"%@",_bottomVc.view);

       }}

转场的代理设置如下:

_navigation.modalPresentationStyle = UIModalPresentationCustom;

_navigation.transitioningDelegate = self;

在使用UIModalPresentationCustom模式进行转场的时候有一个注意点,就是在UIViewControllerAnimatedTransitioning动画控制器中实现代理方法​- (void)animateTransition:(id )transitionContext;时,当用UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];来获得fromView,在转场进入的时候,会为空。所以要使用[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];在返回控制器的View。(注意,在转场出现和转场退出的时候,fromView和toVc是互换的,但是在转场退出时,fromView还是会为空)。

我们可以在类中设置一个成员变量来保持上下文UIViewControllerContextTransitioning,在

-(void)animationEnded:(BOOL)transitionCompleted

{

NSLog(@"toView %@",[_context viewForKey:UITransitionContextToViewKey]);

NSLog(@"fromView %@",[_context viewForKey:UITransitionContextFromViewKey]);

NSLog(@"toVc %@",[_context viewControllerForKey:UITransitionContextToViewControllerKey]);

NSLog(@"fromVc %@",[_context viewControllerForKey:UITransitionContextFromViewControllerKey]);

NSLog(@"toView--vc %@",[_context viewControllerForKey:UITransitionContextToViewControllerKey].view);

NSLog(@"fromView--vc %@",[_context viewControllerForKey:UITransitionContextFromViewControllerKey].view);

}

可以看不同调用方式的情况。

在转场完成和转场退出后,之前的presentedView会丢失,为了在侧滑时可用同时显示两个界面,在转场动画中应该设置一个静态的UIView用来保存presentingView的父视图,在[toVc isBeingPresented]的条件下,我们进行一个保存presentingView = fromView.superview;然后在动画完成时添加[presentingView addSubview:fromView];,在[fromVc isBeingDismissed]的条件下,动画完成时应该这样添加

BOOL isCancel = [transitionContext transitionWasCancelled];

​if (!isCancel) {

[presentingView addSubview:toView];

[fromView removeFromSuperview]; }

最后,代码请到我的Github里面下载,里面还实现了几个非交互转场的方式,都是基于ObjectiveC语言的,欢迎大家交流学习。

Github:​​https://github.com/AirChen/ACTransition

下面这个是以侧滑为基础,模仿QQ的侧滑效果:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标...
    VincentHK阅读 5,359评论 3 44
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥ios动画全貌。在这里你可以看...
    每天刷两次牙阅读 8,480评论 6 30
  • 在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌。在这里你可以看...
    F麦子阅读 5,107评论 5 13
  • iOS视图控制器详解 视图控制器中的视图显示在屏幕上有两种方式:最主要的方式是内嵌在容器控制器中,比如 UINav...
    coder_feng阅读 11,216评论 2 12
  • 前言 正如标题所示,iOS开发中, 自定义转场的过渡动画确实是必须要了解的, 在iOS7之后实现也是很简单的. 如...
    ZeroJ阅读 8,947评论 9 122