[iOS]0 行代码集成 Facebook 和 Twitter 的 Modal 动画

417 阅读4分钟

现在进入正题。没错,就是告诉你 0 行代码拥有 Facebook 和 Twitter 这个动画。

JPPopPresentAnimation.gif

要实现这个功能分两步走:第一步,先实现这个动画。第二步,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,在上下文中我们就可以通过:UITransitionContextFromViewControllerKeyUITransitionContextToViewControllerKey 两个 key 拿到当前的控制器和即将弹出的控制器。

  • 控制器都拿到了,我们就可以拿到控制器对应的 View 进行动画了。

第二步:0 行代码集成到项目

为什么要强调 0 行代码集成到项目?

  • 刚开始写代码的时候,项目老大并没有说要这个动画,你项目都快结束了,他说这个动画挺好,我们也做一个吧(程序员转过身:XXX脏话)。这个时候你已经写了几百个 Modal 动画的代码了,你不可能一个一个去找去改吧?

  • 几百行你改完了,你以为终于完事了,这件事就过去了,结果产品经理一个月以后又跑过来说,这个功能我们还是砍掉吧。(程序员大声:XXXXXX很脏的话)。

所以,这个时候低耦合易集成就显得特别重要。

为了处理这样的需求,所以采用 hook 方案,结合 runtime 来解决。hook 就是钩子的意思。

  • 我们要用这个钩子把系统所有的 Modal 动画的实现都钩出来,然后再把我们自己写的 pop 动画也给钩出来。
  • 然后再运用动态方法交换,将这系统的 Modal 动画和自己的 pop 动画的实现相互替换。
  • 所以以后,我们再调用系统的 Modal 动画的时候,实际上会去方法实现里找我们自己的 pop 动画去执行。这也就是为什么可以 0 行代码集成这个功能的原因。
  • 也有可能我们在某些情况下不需要pop动画,比如说照片浏览器。这种情况很少,所以你只需要写很少的代码,去调用我们自己的 pop 动画。当调用我们自己的 pop 动画的时候,我们的钩子会去找系统的 Modal 动画去执行。

思路就到这里了,具体的实现细节,还需要您自己去Github下载 demo

NewPan 的文章集合

下面这个链接是我所有文章的一个集合目录。这些文章凡是涉及实现的,每篇文章中都有 Github 地址,Github 上都有源码。

NewPan 的文章集合索引

如果你有问题,除了在文章最后留言,还可以在微博 @盼盼_HKbuy 上给我留言,以及访问我的 Github