上一篇文章提到自定义导航条(NavigationBar)覆盖系统返回按钮,导致滑动功能消失的解决方法后,有朋友提出有时候会遇到一些别的要求,比如要设置一个全屏滑动返回的功能,顾名思义在屏幕任何位置都能实现右滑返回。
其实如果滑动功能的解决思路和过程,这个方案并不难实现,或者说比解决滑动功能消失更简单。首先我们可以先解决以下问题:为什么系统手势不能全屏?那我们可以把手势属性打印出来分析。
Edge是边缘的意思,那很有可能系统用这个方法只能控制边缘的滑动返回,我们可以点进去进一步观察。
可见 UIScreenEdgePanGestureRecognizer是继承于 UIPanGestureRecognizer,而且edges这个属性我们也可以确认就是用来控制边缘。那我们可以尝试直接点击进去,看看是否可以直接修改系统的东西实现我们的需求。
如图可见,值得我们参考的只有两个,一个是None,一个是All。字面意思可以推测,None是指没有边界,那意味着是无法滑动。All的话包括上下左右四个方向,即可以向任何方向滑动,也明显不符合我们需求。
所以,那就意味着我们眼下只能创建UIPanGestureRecognizer(下文pan手势替代),并把它加到导航控制器的view上,因为无论如何跳转,导航控制器都会在最底层,能够响应手势。
那我们不用系统手势,自己创建pan手势并添加。那么,下面我们只要实现功能即可。在实现功能之前要先注意到一个问题,我们的系统是否本来就已经存在滑动返回这个功能。既然系统的手势本来就有这个方法,我们也已经把手势添加到整个view上,那我们是否直接把系统的返回功能拿过来使用即可?那么我们再回到最初的打印。
其实第一次打印这个手势时,系统就已经把target和action给出,那就意味着我们可以直接使用,只需在创建时使用系统的target,就能直接调用系统的action方法实现返回功能。
但是这里可能会有个难点,就是我们。如何能拿到系统的target。因为该类我们不能通过方法直接创建(因为该类是私有的,即苹果没有把它暴露给我们,不能直接使用)。但是如上图我们可以注意到还有一个细节, _UINavigationInteractiveTransition和它的代理 self.interactivePopGestureRecognizer.delegate是同一种类型,虽然不是同一个对象,但是我们不用在意它们是否同一个对象,因为这方法是定义在类里面的。所以,我们可以定义一个“假”的target,只要是同一个类,就能调用该方法。
最后会报一个找不到方法的警告,可以忽略它,因为我本来就没有定义这个方法,只是想办法调用了系统本来就写好的方法。本次改动功能实现其实就4行代码,这里主要是提供一个思考过程和大家一起分享。