调整导航条的按钮的位置
在自定义导航条左侧返回按钮,返回按钮明显会有点偏右,应该如何调整的,由于导航栏的NavigationItem是个比较特殊的View,设置Frame是行不通的,在苹果提供的UIButtonBarItem中有个叫做UIBarButtonSystemItemFixedSpace的控件,利用它,我们就可以轻松调整返回按钮的位置,具体代码如下
|
|
然后设置代理
|
|
全屏滑动返回
(1)系统自带的手势是UIScreenEdgePanGestureRecognizer
类型对象,看名字就知道这个是屏幕边缘滑动手势。所以系统自带的滑动效果,自然只能实现侧边滑动。
(2)我们自己给导航控制器添加UIGestureRecognizerDelegate协议,添加一个全屏的滑动手势。然后用新添加的滑动手势,来调用系统实现的滑动返回功能(handleNavigationTransition
方法),这样就实现了全屏滑动功能。
(3)注意:我们还要禁止系统自带滑动手势,同时只有非根控制器才有滑动返回功能,根控制器没有。
|
|
这种方法的原理其实很简单,其实就是自定义一个全屏滑动手势,并将滑动事件设置为系统滑动事件,然后禁用系统滑动手势即可。handleNavigationTransition
就是系统滑动的方法,虽然系统并未提供接口,但是可以通过runtime找到这个方法,因此直接调用即可。
整体滑动返回
虽然实现了全屏滑动返回,但是滑动时的切换依然是系统自带的动画,如果遇到前一个界面的NavigationBar为透明或前后两个Bar颜色不一样,这种渐变式的动画看起来就会不太友好,尤其当前后两个界面其中一个界面的NavigationBar为透明或隐藏时,其效果更是惨不忍睹。
整体滑动返回等于将两个NavigationBar独立开来,因此可以相对完美的解决导航栏滑动切换中的种种Bug。
实现这个效果有三种基本思路
>
- 使用UINavigationController自带的setNavigationBarHidden: animated:方法来实现,每次push或pop时,在当前控制器的viewWillDisappear:中设置隐藏,在要跳转的控制器的viewWillAppear:中设置导航栏显示。
- 在每次Push前对当前页面进行截图并保存到数组,Pop时取数组最后一个元素显示,滑动结束后调用系统Pop方法并删除最后一张截图。
- 使用iOS 7之后开放的,UIViewControllerAnimatedTransitioning协议,来实现自定义导航栏转场动画及交互。
三种方法中,方法一十分繁琐,且会有很多莫名其妙的BUG,直接pass。
在iOS的交互中,push一般通过按钮的点击事件或View的tap事件触发,而pop则可能通过事件触发,也可能通过右滑手势触发。因此,我们将这个我们要实现的动画效果分为交互效果和无交互效果两种。分别实现这两种效果,可以较为完美的解决Push和Pop的动画问题。
实现交互动画效果
方法二
|
|
实现非交互动画效果
实现原理
注:FromVC代表即将消失的视图控制器,ToVC表示将要展示的视图控制器
要实现的效果:
Push的时候,FromVC往左移动,ToVC从屏幕右侧出现跟随FromVC左移直至FromVC消失,此时ToVC刚好完整显示在屏幕上。
Pop的时候,FromVC向右移动,ToVC从屏幕边缘出现跟随FromVC向右移动直至FromVC消失,此时ToVC刚好完整显示在屏幕上
实现的时候,我们依然需要将Push和Pop分开讨论
先说Pop
1.和交互式动画一样,每次Push时对屏幕截屏并保存,Pop的再次截屏但不保存
2.把Pop时截取的图片作为FromVC展示,把Push到这个界面时截取的图片作为ToVC展示
3.并对两张图片做位移动画,动画结束后移除两张图片
然后是Push
1.Push时先对当前屏幕截屏。
2.将截取的图片保存方便Pop回来时使用,并把这张图片作为这次Push的FromVC保存。
3.获取当前导航栏控制器对象,调整其Transform属性中的位移参数作为ToVC展示
4.对截图和导航栏做位移,动画结束后直接移除截屏图片
为什么要对导航栏作位移?
首先,在Push结束之前,我们是无法知道ToVC具体是什么样子,系统的截屏方法对于未加载出来的View是无能为力的,而UIView的 snapshotViewAfterScreenUpdates:方法又无法带着导航栏一起映射到一个新的View上,因此视觉效果很差。
正好在Pop的时候,为了达到想要的动画效果,用来展示的两张图片都需要放到导航栏的View上,因此在Push的时候我们就直接将导航栏的View做一个放射变换,当然,这也就意味着,当我们Push的时候,截屏就不能再放到导航栏上,而是应该放到它的“更上一层“ – UITabbarController的View上。
话不多说,附上代码如下
AnimationController
创建动画控制器。更准确的说,需要实现的细节都在UIViewControllerAnimatedTransitioning中
|
|