UINavigationController 全屏 pop(2)之为每个控制器添加底部联动视图

声明:我为这个框架写了三篇文章:
第一篇:[iOS]UINavigationController全屏pop之为每个控制器自定义UINavigationBar。这篇文章主要是讲述如何实现自定义导航栏的,所有的思路和实现都是 JNTian的。
第二篇:[iOS]UINavigationController全屏pop之为每个控制器添加底部联动视图。这篇文章讲述,如何在已有的自定义导航栏基础上添加自定义的“底部联动视图”。所有的思路和实现都是我自己的。
第三篇:[iOS]UINavigationController全屏pop之为控制器添加左滑push。这次将讲述如何实现左滑push到绑定的控制器中,并且带有push动画。


112122663-f6bfe46dfc790852

框架特性

✅ 全屏pop手势支持
✅ 全屏push到绑定的控制器支持
✅ 为每个控制器定制 UINavigationBar 支持(包括设置颜色和透明度等)
✅ 为每个控制器添加底部联动视图支持
✅ 自定义pop手势范围支持(从屏幕最左侧开始计算宽度)
✅ 为单个控制器关闭pop手势支持
✅ 为所有控制器关闭pop手势支持


Tips : 阅读本文之前,建议先阅读我之前的文章。因为这篇文章是基于之前文章继续封装的。

Q&A:Demo里都有那些东西?

01、关于自定义导航栏
  • 01、第一个控制器的导航条是透明的,第二个控制器的导航条是白色的,第三个控制器的导航条是橙色的。
    所以,为每个控制器定制自己的导航条。
  • 02、支持全屏右滑,这简直是必须的。关于全屏右滑,最详细,也最早探究这个问题的,我了解到的是 J_雨 ,他应该是全屏右滑的鼻祖。
  • 03、最重要的一点,要求全屏右滑返回的时候,导航条跟随自己的控制器流畅的滑动。
  • 04、以下属于更新的内容,为全屏右滑Pop手势添加滑动起始点控制API。也即是,你可以精确控制从离屏幕左侧起多长距离内右滑,Pop手势是有效的。
  • 05、某些同学和我说,他们在某些界面需要临时关闭Pop手势,让我处理一下。现在已经处理好了,你可以临时关掉Pop手势,等你需要的时候再次打开。
02、此次新增加自定义底部联动视图
 192122663-64a0f8fae4e312c3

现有问题

  • 某些同学做购物软件,可能需要在某个控制器屏幕最下方一直悬浮一个“立即购买”、“马上咨询”之类的控件。有经验的同学遇到此类功能时可能会采用新建一个Window,然后再把自己需要的控件添加到这个Window上,然后设置这个Window的hidden = NO,就可以实现了。确实是这样,其实除了新建一个Window,你还可以将自己的控件添加到当前KeyWindow上,同样可以实现这个功能。
  • 这个功能实现了,但是有一点很恶心的是,苹果自从iOS7开始,有了右滑手势这个东西。这个时候,相比于安卓前进后退按钮是单一的在窗口显示一个控制器,右滑手势可以让窗口同时显示两个控制器的View。
  • 如果你按照上面添加Window或是添加在KeyWindow上的方式。第一、你就不能让你定义的这个控件随着用户右滑而右滑。第二,你只能在这两个方法里控制你的控件的显示和隐藏。但是试过以后你会发现,当用户右滑的时候,你的控件一直在跳跃闪烁。但是我们是有追求的程序狗,我们显然会对这种方案SAY:FUCK AWAY!THIS IS SO UGLY MAN. AND IT SMELLS LIKE SHIT.

解决方案

  • 此次我结合之前的自定义导航栏,给出了一个比较“优雅”的解决方案:
  • 假如A是根控制器,B是下一个要Push过去的控制器,你只需要在A里Push方法后写如下一行。你就可以拥有一个和导航栏一样跟随用户右滑而流畅滑动的“联动”TabBar了,并且你不用关心这个TabBar 的显示和隐藏。

01、之前文章讲了啥?

看到我这篇文章的同学99%都是没有看过我之前那篇文章的,所以我有必要再重新描述下之前文章的内容。但是如果你要详细了解实现思路还是需要回头看我那篇文章,因为这篇文章我是讲底部联动视图的,所以NavgationController不会讲的很细。
之前的文章大致说清楚了,怎么样去适应需要为每个界面都定制导航条的需求。
实现思路如下:

  • 当我们调用这个initWithRootViewController构造方法的时候,先用一个JPNavigationController作为根控制器,负责所有的Push和Pop操作。
  • 然后当用户调用Push方法的时候,先将用户传进来的控制器A用一个JPWarpNavigationController(继承UINavigationController)包装起来成为B,然后再将B用一个JPWarpViewController包装起来成为C,然后用根导航控制器JPNavigationController来Push和Pop。
  • 经过这样包装以后,每一个控制器都拥有一个自己的导航条,所以,用户可以对每个导航条进行定制,比如说透明、颜色、渐变等操作。
  • 之所以要进行这两层包装的原因是苹果默认的规则是导航控制器不能Push和Pop导航控制器。

02、导航栏更新部分实现思路?

实现目标:1.临时关闭Pop手势 2.自定义右滑手势有效区域

  • 系统的interactivePopGestureRecognizer只提供了一个enabled的属性给我们,所以如果想要做更多的事就要想其他的办法。在这种情况下,我选择了自定义一个UIPanGestureRecognizer,替换系统的手势的实现
  • 这样我们用自己的手势替代了系统的右滑功能,所以我们可以在自定义的手势代理方法中自定义右滑的特性:

03、自定义底部联动视图?

  • 自定义的底部联动视图应该必须满足两点:1.跟随用户滑动而流畅的滑动 2.不需要在viewWillAppear和viewWillDisappear中处理TabBar的显示和隐藏。
  • 要满足以上两点,首先要考虑的是,我们的底部联动视图的父控件应该是谁?
  • 从以上的分析大概也可以知道如果我们把TabBar添加到导航栏上,我们需要达到的要求就都满足了。
  • 为了方便大家使用,我先定义一个占位容器视图JPLinkContainerView,我把它添加到导航栏上,作为导航栏的子控件,以后使用的时候,~只需要往这个占位视图上添加你自己的TabBar控件就可以了。~ 你只需要把你的联动视图传给框架就可以了。
  • 当我们把联动的JPLinkContainerView添加到导航条上以后,联动视图就超出父控件的范围,不能响应点击事件了。所以首先我们要做的就是自定义一个JPNavigationBar替换掉系统的导航条。借助于KVC,我们可以实现这一点。
  • 现在我们自定义了导航条,我们就可以在JPNavigationBar中重载hitTest方法,在这个方法中遍历它自身的子控件,找到我们添加的JPLinkContainerView。当点击的点在我们添加的占位容器视图JPLinkContainerView身上的时候,我们就手动把点击事件分发给我们自定义的TabBar子控件上,完成响应者链条的事件传递。

04、使用注意点?

1.关于联动底部视图的高度

使用时注意 : 如果你下个界面需要有联动底部视图, 你在上个控制器 – (void)pushViewController:animated:方法后面立即把值传给框架:

同时注意 : 这两行代码有逻辑关系,必须先调用push方法,navigationController才会alloc,分配内存地址,才有值。

2.关于联动底部视图

~需要添加自定义的视图的时候,只要把自定义的视图添加到这个视图上就可以了~
你只需要在viewDidLoad:方法里把你的联动视图传给框架, 框架会制动帮你显示。

注意 : 如果识别到你当前控制器为UITableViewController的时候, 如果有联动底部视图, 就会自动为你添加jp_linkViewHeight高度的底部额外滚动区域。 但是, 如果你的控制器是UIViewController上添加了UITableView, 那我不会自动为你添加底部额外滚动区域, 需要你自己为UITableView添加contentInset。

05、这个框架用到的知识点?

06、Demo地址?

框架的Github地址在这里[JPNavigationController]。如果我的文章在你实际工作中恰好帮到了你,请你给个小星星,谢谢。如果你和我一样热爱开源、热爱分享,或许可以小手一抖,帮我转发给更多朋友看到。

07、更新

  • 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。

我的文章集合

下面这个链接是我所有文章的一个集合目录。这些文章凡是涉及实现的,每篇文章中都有GIT地址,GIT上都有源码。如果某篇文章刚好在你的实际开发中帮到你,又或者提供一种不同的实现思路,让你觉得有用,那就看看这句话 “坚持每天点赞的人,99%都是帅哥美女,再也不用单身了😀”

 

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

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部