用过Facebook和Twitter的同学应该尤其喜欢他们的动画,但是动人心弦的动画都是用时间堆出来的,可是程序员的时间... 各位同学,写完代码,就去陪老婆吃一顿饭吧,程序员老婆不容易。
现在进入正题。没错,就是告诉你0行代码拥有Facebook和Twitter这个动画。
要实现这个功能分两步走:第一步,先实现这个动画。第二步,0行代码集成到项目。也就是,你不用改原有项目的任何代码,只要把写好的动画代码拖进项目,以后所有的Modal就拥有这个动画了。
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion
好,准备好了吗?现在开始。
第一步:先实现这个动画
-
首先我们来分析一下这个动画,这个动画就是在Modal的时候拿到当前控制器的View,然后在Modal的过程中将这个View的尺寸缩小。然后在Dismiss的时候拿到这个View,将它尺寸恢复成原有的大小。就这么多了。
-
怎么在modal动画中拿到当前的控制器的View?这个很简单,只要你设置动画样式为自定义,并且成为弹出动画的代理,就像这样:
self.modalTransitionStyle = UIModalPresentationCustom; viewControllerToPresent.transitioningDelegate = self;
然后在代理方法中,会询问转场动画的提供者,此时,你再去新建一个JPTransitionManager作为转场动画的提供者。
// 询问转场动画的提供者 - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source; - (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;
-
在这个转场动画的提供者里,我们继承NSObject,然后遵守
UIViewControllerAnimatedTransitioning协议,然后实现协议中这两个方法:- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext; - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext;
第一个方法是询问动画的时长的。第二个方法中我们可以拿到准备做Modal动画的上下文transitionContext,在上下文中我们就可以通过:UITransitionContextFromViewControllerKey和UITransitionContextToViewControllerKey两个key拿到当前的控制器和即将弹出的控制器。
-
控制器都拿到了,我们就可以拿到控制器对应的View进行动画了。
第二步:0行代码集成到项目
为什么要强调0行代码集成到项目?
- 刚开始写代码的时候,项目老大并没有说要这个动画,你项目都快结束了,他说这个动画挺好,我们也做一个吧(程序员转过身:XXX脏话)。这个时候你已经写了几百个Modal动画的代码了,你不可能一个一个去找去改吧?
- 几百行你改完了,你以为终于完事了,这件事就过去了,结果产品经理一个月以后又跑过来说,这个功能我们还是砍掉吧。(程序员大声:XXXXXX很脏的话)。
所以,这个时候低耦合易集成就显得特别重要。
为了处理这样的需求,所以采用hook方案,结合runtime来解决。hook就是钩子的意思。
- 我们要用这个钩子把系统所有的Modal动画的实现都钩出来,然后再把我们自己写的pop动画也给钩出来。
- 然后再运用动态方法交换,将这系统的Modal动画和自己的pop动画的实现相互替换。
- 所以以后,我们再调用系统的Modal动画的时候,实际上会去方法实现里找我们自己的pop动画去执行。这也就是为什么可以0行代码集成这个功能的原因。
- 也有可能我们在某些情况下不需要pop动画,比如说照片浏览器。这种情况很少,所以你只需要写很少的代码,去调用我们自己的pop动画。当调用我们自己的pop动画的时候,我们的钩子会去找系统的Modal动画去执行。
思路就到这里了,具体的实现细节,还需要您自己去Github下载 demo 。
One more thing ?
如果您对“hook技术”想有一个相对全面的了解,或许可以参见我的另外一篇文章“1行代码快速集成按钮延时处理(hook实战)”。我在这篇文章详细的阐述了鄙人对“hook技术”的见解。
来自:http://www.jianshu.com/p/910d7825f06a