前言
现如今 App 的体验越来越重要,我们的 App 中也要求加入更多的动画效果,其中最广泛的是转场动画,由于需要批量的加入转场动画,如果于每一个 VC 中去添加修改是一件费时费力的事情,所以有了下面要介绍的一个开源组件 –WKAnimatorManager
功能介绍
实现了对转场动画的封装以及左滑的集中处理。
优点:集成方便,使用简单,拓展性强。
简要介绍
转场管理结构中只有四个类:
UINavigationController+WKTransitions
功能:hook 了 UINavigationController 的部分方法,实现集成即可使用。其一:hook 了 push,pop 系列方法,于其中设置动画转场子类,便于统一处理动画其二:重写了 viewdidload 设置 UINavigationController 的转场代理为 WKAnimatorManager 的单例
UIViewController+WKTransitions
功能:hook 了 UIViewController 的部分方法以及新增了两个属性,实现集成即可使用。其一:为 UIViewController 添加了两个转场动画属性,一个用于模态转场 wk_modelAnimator,一个用于导航栏转场 wk_navAnimator,均为 WKBaseAnimator 的子类其二:hook 了 dismiss 以及 present 模态转场方法,便于统一处理动画其三:hook 了 init,讲其模态转场代理设置为 WKAnimatorManager 单例
WKAnimatorManager
功能:遵循模态以及导航栏转场协议,集中处理转场逻辑内部自定义了 UIScreenEdgePanGestureRecognizer 手势,实现左滑返回逻辑自处理。
WKBaseAnimator
功能:动画处理基类自定义动画只需要继承自此类,将动画效果写于 present 以及 dismiss 方法即可。如需左滑手势返回,系统只支持了 view 层级动画的左滑返回操作,所以左滑返回动画必须为 view 层级动画,其次需设置 edgeType 为 UIRectEdgeLeft 即可。
使用方式
步骤一、
下载 Demo,将 Demo 里的 Transitions 文件夹拖入项目,再将已整合好的头文件 WKAnimatorManagerHeader.h 加入全局头文件.pch 中。
步骤二、
创建继承自 WKBaseAnimator.h 的自定义动画类,下面以 Demo 中已存在的的动画作为例子(后面有效果展示):
#import “WKBaseAnimator.h”
@interface MagicMoveTransition : WKBaseAnimator
// 自定义需要的属性
@property (nonatomic, assign) CGRect endRect;// 终点
@property (nonatomic, strong) UIView * sourceView;
@end
于.m 文件中实现从父类继承而来的 present 以及 dismiss
– (void)present{
[UIView animateWithDuration:[self transitionDuration] delay:0.0f usingSpringWithDamping:0.8f initialSpringVelocity:1.0f options:UIViewAnimationOptionCurveLinear animations:^{
…..
} completion:^(BOOL finished) {
…..
// 告诉系统动画结束
[self completeTransition];
}];
}
– (void)dismiss {
…..
// 发生动画
[UIView animateWithDuration:[self transitionDuration] delay:0.0f usingSpringWithDamping:0.8f initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
…..
} completion:^(BOOL finished) {
…..
// 告诉系统动画结束
[self completeTransition];
}];
}
可自定义动画执行时间
– (NSTimeInterval)transitionDuration{
return 0.6f;
}
支持左滑返回可以这样,在初始化时将其边界 type 修改为 left
– (instancetype)init
{
self = [super init];
if (self) {
self.edgeType = UIRectEdgeLeft;
}
return self;
}
步骤三、
在 push 或者 present 之前为 vc 设置上对应的动画
– (void)gotoWindoeModelVC
{
WindowModelVC * vc = [WindowModelVC new];
WKWindowedModelAnimator * animator = [WKWindowedModelAnimator new];
animator.toViewHeight = SCREEN_HEIGHT / 2.f;
// vc.wk_modelAnimator = animator;
// [self.navigationController presentViewController:vc animated:YES completion:nil];
// 都可以啊
vc.wk_navAnimator = animator;
[self.navigationController pushViewController:vc animated:YES];
}
效果展示
在 Demo 中提供了一些常用的转场动画的封装,可直接使用。
更多自定义的效果,可参考 WKAnimatorManager 的 Demo。
后记
既然各位看到这了,再给大家分享一个小知识。
在我实现自定义侧滑(UIScreenEdgePanGestureRecognizer)时,发现设置了其 edges 为 UIRectEdgeLeft 时,手势被触发的时机并不是在我进行侧滑时,而是在全屏任何一个地方都会触发这个手势。这一度对我造成了困扰。
那么从触发手势开始思考,手势一开始于屏幕上触发(硬件层面),实质在这个层面是不会也不应该去做任何判断其手势的合法性,而是直接传递到系统由软件来判断其合法性,那么为什么我设置了 UIRectEdgeLeft 这个值之后,却没有达到预想的效果呢。带着这个疑问,我去拦截了系统的侧滑手势,发现其也是全屏可以被触发,只是一开始是 UIGestureRecognizerStatePossible 状态,然后如果其起始点超过 50 则变为了 UIGestureRecognizerStateFailed 状态,而小于等于 50 时则进入 UIGestureRecognizerStateBegan 状态,开始执行手势。
那么接下来就简单了,我们只需要实现下面一个代理方法即可实现完全和系统一模一样的侧滑手势了。
// 系统左滑返回 x 实现方式
– (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer == self.edgePan) {
UIScreenEdgePanGestureRecognizer * pan = (UIScreenEdgePanGestureRecognizer *)gestureRecognizer;
CGPoint point = [pan locationInView:self.edgePanVC.view];
return (point.x < 50);
}
return NO;
}