声明:我为这个框架写了四篇文章:git
第一篇:[iOS]UINavigationController全屏pop之为每一个控制器自定义UINavigationBargithub
第二篇:[iOS]UINavigationController全屏pop之为每一个控制器添加底部联动视图架构
✅ 全屏 pop 手势支持性能
✅ 全屏 push 到绑定的控制器支持动画
✅ 为每一个控制器定制 UINavigationBar 支持(包括设置颜色和透明度等)3d
✅ 为每一个控制器添加底部联动视图支持code
✅ 自定义 pop 手势范围支持(从屏幕最左侧开始计算宽度)cdn
✅ 为单个控制器关闭 pop 手势支持
✅ 为全部控制器关闭 pop 手势支持
❤️ 当当前控制器使用 AVPlayer 播放视频的时候, 使用自定义的 pop 动画以保证 AVPlayer 流畅播放.
说明:有不少同窗,包括你能看到,留言栏里也有同窗说原做者不推荐使用这个框架。而后就来问我,是否能在本身的项目里引入这个框架。从技术的角度来讲,我我的的想法是,你要尝试本身去衡量。可能不少同窗都看到原做者不推荐,可是却没注意不推荐的缘由:“细节问题会比这个完善不少”。我不解释,只把缘由单独贴出来了。补充一点,凡是我在本身的项目中使用碰到的细节问题,都已经修复好了。
有一个同窗担忧性能问题,他的担忧是有依据的,由于毕竟通过包装处理之后,之前每次只须要压入一个控制器到栈,如今是每次压入三个。其实碰到这种问题,我是尝试去作循环利用的,可是因为这里问题的特殊性(为何特殊?),我至今仍在思考合适的方法可以达成循环利用的效果。为了解除这部分同窗的疑问,你可使用如下网易云音乐,他们是这种模式的缔造者,同时经过Reveal观察,没有迹象代表他们实现了这部分的循环利用,这就是我对性能问题的交代。若是有一天我找到了一个合适的方式来作循环利用我确定还会写一篇文章来讲明这个过程的。
As we all know,Apple 提供的导航条是用来管理窗口控制器的结构的,某个 UINavigationController
执行 Push
操做后,该导航控制器管理的 controllers
共用一个导航条,若是对该导航条进行自定义,那么各个界面的导航条都会变成自定义之后的样式。可是,实际开发中,咱们可能须要为不一样的控制器定制不一样的导航条,就像我 demo 里写的同样.
UITabBarController
做为根控制器管理着一个导航控制器和一个 UIViewController
UITableViewController
,为了完整的显示图片,该 UITableViewController
的导航栏要求是透明的用 Reveal 观察了几个经常使用 App,发现了这种效果的实现大体分3种:
第一种是使用自定义 navigationBar
.淘宝,网易新闻,达令等使用的是这种. 第二种是用截图的办法,在 push
到下一个页面时,截取屏幕,在使用 edgePan
来 pop
时看到的就是背后的截图,也能实现这种效果.京东,天猫等使用的是这种. 第三种是使用了一种比较特别,比较巧妙的办法实现的,也就是网易云音乐的实现方法,后面会分析一下这种实现.
做者用 Reveal 工具考察了实现这一效果的三种已知的方式,在对比这三个实现方式各自的优缺点之后,采用了第三种方式来实现。
要探究实现,先要讲清楚一个原则:
UINavigationControler
嵌套 UINavigationControler
的方式是不被容许的,也不能执行压入栈 push
和出栈 pop
动做跟我看三张图:
还记得开头的 demo 吗?demo 的结构就是这样一个窗口结构图:
TabBarController
(上图紫色的 view
)TabBarController
每个分支子控制器,用一个根导航控制器做为管理者(上图小一点的黑色 View
)setNavigationBarHidden:
将根导航控制器的导航栏完全移除rootViewController
和 push
入栈的时候,要先将传进来的控制器(上图蓝色的 View
)先包装一层导航控制器(上图白色的View
)UINavigationControler
嵌套 UINavigationControler
的方式是不被容许的,也不能执行压入栈 push
和出栈 pop
动做View
)外层再包装一层 UIViewController
Controller
就拥有了一个本身专有的导航控制器,咱们能够在对应的控制器的 .m
文件里对该导航控制器作任何自定义(设置透明度和颜色以及渐变)上面两张图,咱们分析了怎么设定根视图的结构,以及怎么包装用户传进来的控制器。 有了以上的基础之后,咱们就能够进行入栈和出栈的操做了。 注意:
TabBarController
每个分支子控制器的 push
和 pop
操做都是由根导航控制器负责pop
和 push
操做的对象都是咱们包装事后的 WarpViewController
,这样就不会有导航控制器 push
和 pop
导航控制器的冲突了代码实现见 GitHub。或者也能够参见原做者的 Github地址。我只是在原做的基础上加了注释,并无修改代码。 若是你对demo中图片在tableView滚动时的视差效果感兴趣,能够参见我之前的文章 仿Airbnb的tableView头部视图层叠效果。 最后,谢谢Github开源做者: JNTian,大写的感谢。
2016.08.02: 有朋友在QQ上联系我说,他在实际开发中有须要在某个界面暂时关闭右滑手势的需求。因此,加入暂时关闭右滑手势开关,方便在某些状况下须要暂时关闭手势。具体更新见个人GitHub_Demo。
2016.08.04: 上个版本使用类工厂方法,在类工厂方法里操做了用户传进来的控制器的View,因此会形成在应用启动的时候TabBarVC的子控制器一块儿加载,有性能问题.此次提交修复了这个问题, TabBarVC的子控制器都能遵循懒加载的原则.谢谢:袁小荣同窗(Github)的提醒.
2016.08.08: 这个框架有了较大的更新。具体包括给现有的Pop手势添加暂时关闭开关,以及自定义响应手势范围。在现有基础上,框架添加了底部联动视图,具体实现以及思路,请前往个人文章:1行代码为每一个Controller自定义“TabBar”。
2016.09.13 添加了直接拿到根导航控制器的接口,方便使用popToViewController功能。具体见demo第三个控制器的Pop。
注意: tabBar 的 translucent 默认为 YES, 使用 JPNavigationCotroller 不能修改 tabBar 的透明属性. 这是由于 Xcode 9 之后, 苹果对导航控制器内部作了一些修改, 一旦将 tabBar 设为不透明, 当前架构下的 UI 就会错乱, 设置 tabBar 的 backgroundImage 为不透明图片, 或者设置 backgroundColor 为不透明的颜色值也是同样的会出错.