iOS11 导航栏按钮位置问题的解决——新
之前有写过iOS11导航栏按钮位置的一篇解决方案,当时的解决思路是针对navigationItem做调整,强制修改约束
具体细节可以跳转
iOS11 导航栏按钮位置问题的解决
http://blog.csdn.net/spicyshrimp/article/details/77891717
但是后期发现这个解决方案仍有许多问题
1.界面在push和pop之后约束会失效,当时的解决方案是写在viewWillAppear中屏蔽,但是这样就造成了如果使用的话可能会有很多开发者不习惯
2.删除约束的问题,虽然有强制修改约束,但是针对不同的开发者的应用,约束条件可能会有所变动,所以可能不适应所有方式
3.多个按钮的设置没有写,很多人会出现疑惑
4.偶发的约束失效,或者其他问题
新的思路,
之前有人是修改button的位置偏移或者点击区域等来调整,但是这样多个按钮就会出现重叠和按钮点击区域无效的情况,所以就没有考虑
至于自定义控件,比如自定义bar或者自定义view等不作为考虑对象,此次的目的是修改系统的导航栏
扩展系统的导航栏,在系统的导航栏中进行约束调整.
开始的思路是类似之前的写法.删除不需要的约束,重新添加新的约束用以限制位置,也确实实现了,但是这样的方式跟之前仍然是一样的问题
或造成push和pop的约束丢失
于是想到了layoutMargins这个属性
我们遍历图层大致可以看到这样的
<_UINavigationBarContentView: 0x7fc141607250; frame = (0 0; 414 44); layer = <CALayer: 0x608000038cc0>>
这个UINavigationBarContentView平铺在导航栏中作为iOS11的各个按钮的父视图,该视图的所有的子视图都会有一个layoutMargins被占用,也就是系统调整的占位,我们只要把这个置空就行了.那样的话该视图下的所有的子视图的空间就会变成我们想要的那样,当然为了保险起见,该视图的父视图也就是bar的layoutMargins也置空,这样 整个bar就会跟一个普通视图一样了 左右的占位约束就不存在了
于是就出现了这样的代码
@implementation UINavigationBar (SXFixSpace)
+(void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self swizzleInstanceMethodWithOriginSel:@selector(layoutSubviews)
swizzledSel:@