0行代码集成非死book和推ter的Modal动画

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