一行代码实现自定义转场动画

前言

系统自带的presentViewControllerpushViewController已经能够很好的完成场景与场景之间的过渡了,而且提供的动画视觉效果也很简洁流畅,称之为iOS系统的标志之一也不为过。
但是如果能让转场过程根据业务情景做一些更丰富,或者说是更适合的动态表现,其实也不失为一种内容表达上的点睛之笔。

通过拜读两位大神:KittenYangOneV's Den的系列文章,逐渐尝试、总结,输出了这套专注于自定义转场动画的工具:XTTransitionAnimations
这里不再赘述转场动画的实现原理,有需要的小伙伴可以到两位大神的文章学习下~ 也欢迎留言讨论~

实现功能

一行代码实现自定义转场动画
[self XT_PresentViewController:vc animatedType:XTSpringFromBottom interact:NO completion:nil];

[self.navigationController XT_PushViewController:vc animatedType:XTRoundExpand interact:YES];
  • 与系统原生的present和push转场api极其相似,学习成本低;
  • 支持动画效果参数配置,如时长,阻尼系数,弹性曲线等;
  • 可配置转场动画是否可交互;
  • 侵入性很低,不对UI层干涉;
  • 默认生成配套的dismiss/pop动画,也可单独配置;
  • 可交互动画中,弹性动画与线性动画自动切换。

工具目前内置四类自定义动画(后续会继续拓展),使用时通过枚举类型参数设置即可;目前主要实现的动画效果有以下四类:


Spring From Bottom(present,interact,XTSpringFromEdgeAnimation)

Spring From Right(push,interact,XTSpringFromEdgeAnimation)

Round Spring Expand(present,interact,XTRoundExpandAnimation)

Card Spring From Bottom(present,interact,XTCardPresentAnimation)

Cube Rotate From Right(push,interact,XTCubeAnimation)

Cube Rotate From Top(present,interact,XTCubeAnimation)
只需实现动画对象就可以自定义你自己的转场动画

工具支持动画种类扩展。主要流程如下:

  1. 生成一个实现你想要的效果的服从UIViewControllerAnimatedTransitioning协议的动画对象(例如Animations文件夹中的类);
  2. (可选)如果手势滑动距离控制转场动画进度的交互方式并不能满足你的需求,可以生成一个继承于XTBaseInteractiveObj的子类,来定制交互方式(例如Interactive文件夹中的类);
  3. 完成XTAnimationsConfig.plist中动画的基本配置;
  4. 最后维护convertAnimationTypeEnumToStr:方法(将枚举类型转换为字符串)。

即可使用工具统一的api完成自定义转场动画的使用。

解释一下XTAnimationsConfig.plist的用处:

除了之前说的阻尼系数等非普适性参数(不是每个动画都需要的参数),对于一些所有动画都需要的基本参数,例如,实现类,实现交互的类,交互完成的标志等等,就是通过XTAnimationsConfig.plist来配置的。 其中有多个字典,每个字典对应一个动画类型(XTAnimationType)。下面具体来介绍一下,其中各键的意义:

  • animationClass:实现该动画需要的类的类名(Animations文件夹中的各个类);
  • interactiveClass:实现交互所需的配置;
    • className:该动画实现交互所需的类的类名(Interactive文件夹中的各个类);
    • isVertical:由于一般的交互是通过手势控制的,而且大多与手势的移动距离有关,因此该属性配置当前交互的进度是与竖直方向还是水平方向的位移有关;
    • isAccordToCoordinate:动画完成进度的变化趋势是否与屏幕的坐标体系一致,即位移为正值逐渐变大时,是否完成进度也在逐渐变大;
    • completePointNum:动画完成所需要位移的点数;
      • ScreenHorW:点数是基于屏幕的高还是宽来计算(W:宽;H:高);
      • percent:点数占屏幕宽或高的百分比;(通过以上两个参数计算完成过场动画所需的位移点数)
      • absolutePointNum:输入具体的点数,位移距离达到指定点数则当前动画达到完成条件(优先于以上两个参数生效)

使用方法

引入头文件

#import "UIViewController+XTTransitionAnimations.h"
#import "UINavigationController+XTTransitionAnimations.h"
Present
/**
 根据animatedType定制present时的转场动画,默认dismiss返回时有配套的转场动画。

 @param viewControllerToPresent 弹出的VC
 @param aniType 动画种类
 @param isInteract 转场动画是否可交互
 @param completion 完成动画时的回调
 */
-(void)XT_PresentViewController:(UIViewController *)viewControllerToPresent animatedType:(XTAnimationType)aniType interact:(BOOL)isInteract completion:(void (^)(void))completion;
定制Dismiss
/**
 如果不想使用present配套的转场动画 或 只需要dismiss时出现转场动画,可使用该方法单独定制dismiss时的转场动画。
(1.建议在需要dismiss的VC初始化完成后,视图展示之前,例如viewWillAppear中调用该方法完成配置,否则会出现交互部分仍按XT_PresentViewController中设置的配套动画执行的情况;
 2.不建议某些关联性较强的present和dismiss动画,例如XTCardSpringFromBottom等,使用此方法定制动画,视觉效果会很差;
 3.在正确位置调用该方法完成配置后,需要dismiss时直接调用系统的popViewControllerAnimated:方法即可。)
 
 @param aniType 动画种类
 @param isInteract 转场动画是否可交互
 */
-(void)XT_ConfigureDismissWithAnimatedType:(XTAnimationType)aniType interact:(BOOL)isInteract;
Push
/**
 根据animatedType定制push时的转场动画,默认pop返回时有配套的转场动画。

 @param viewController push到的VC
 @param aniType 动画种类
 @param isInteract 转场动画是否可交互
 */
-(void)XT_PushViewController:(UIViewController *)viewController animatedType:(XTAnimationType)aniType interact:(BOOL)isInteract;

以上就是这套工具的大致介绍,希望大家多多指正、讨论!
如果觉得对你有一点用的话,也希望你能动动你的小手,来个赞啊、star啊什么的~
如果有小伙伴觉得这套框架的思路还行,更希望大家一起来实现更多的动画效果!

Github地址


看啊!这里有个坑!

这里主要就是分享在写转场动画过程中遇到的坑。

  1. layer层的全部动画,类似于
[xxLayer addAnimation:pathAni forKey:[NSString stringWithFormat:@"%@",self.class]];)

的这种动画,在iOS11中,对进度的控制全部无效!也就是说,在继承于UIPercentDrivenInteractiveTransition的负责交互的对象中,使用updateInteractiveTransition:来更新动画进度,是不生效的,动画只要一开始,就正常执行一直到结束,丝毫不受传入的进度参数影响。同样代码,在iOS10中测试,是没有问题的。
而且,即使在iOS10中,在交互过程中,如果交互程度没有超过交互完成点,最后通过cancelInteractiveTransition取消了交互,view层的动画,可以让动画按照“原路”返回初始状态,但layer层动画并不能,直接瞬间填充;超过结束完成点,但还有部分可视内容时,也直接瞬间消失,而不是像view动画那样继续动画到最终完成状态。
通过查阅资料,在iOS11中,系统对view的动画进行了相当多的扩展,所以,我很大胆的猜想了一下,是不是Apple在引导开发者向view动画进行倾斜呢?但就算真是这样,也不应该直接就悄无声息的改掉啊?没有任何书面的说明?
希望有大神能够批评指正。
因此,在iOS11中,工具中的XTRoundExpandAnimation动画类型,暂时不支持交互。。。(日后会争取实现非layer动画的实现方式)

  1. 动画完成后,一定要还原view的所有形变。实现转场动画时,可能会对view的某些参数,例如anchorPoint、position等影响布局的参数进行修改,因此,如果在动画完成后,如果不将其还原的话,会影响之后view上的UI展示层效果;而且,当自定义的转场动画,相互叠加时,例如present一个navVC,navVC中再相互push,最后再其中某一个dismiss,那么影响将更明显。

  2. 在动画对象的- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext方法中实现动画时,一定要使用根据transitionContext生产的frame等参数,不要使用屏幕大小等方式来获取,不然的话在稍微复杂一点的动画中,就会出现无法准确获得view的关键节点状态值的情况,造成动画效果达不到预期。

  3. 在Present的转场过程中,还有一个利器,就是UIPresentationController。个人认为,他是iOS8.0中出现的一个对animationControllerForPresentedControlleranimationControllerForDismissedController进行简易封装的api,而且监控的粒度更细。大多数人都是将他与animationControllerForPresentedControlleranimationControllerForDismissedController结合着进行使用,但是个人认为,他也可以独立完成Present转场动画的实现,而且这样与Push转场动画的实现逻辑很相似。但是,他无法独立完成动画的交互实现。
    如果真的要结合在一起使用的话,注意其和animationControllerForPresented/DismissedController之间对视图的作用是同时生效的,因此要注意各司其职,不要出现反复添加、处理视图之类的问题。

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

推荐阅读更多精彩内容