[置顶] iOS11 导航栏按钮位置问题的解决------新
2017-10-11 10:44
585 查看
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:@selector(sx_layoutSubviews)]; }); } -(void)sx_layoutSubviews{ [self sx_layoutSubviews]; if (deviceVersion >= 11) { self.layoutMargins = UIEdgeInsetsZero; for (UIView *subview in self.subviews) { if ([NSStringFromClass(subview.class) containsString:@"ContentView"]) { subview.layoutMargins = UIEdgeInsetsZero;//可修正iOS11之后的偏移 } } } } @end
是的,这一次的修正方式何其的轻松,之前饶了太多的弯路….
于是在结合iOS11之前的特性,和并出新的解决导航栏按钮问题的新的解决方案,
这一次,修正的更加彻底
相较于上一次的优势,
1.可以使用itmes方式设置多个按钮
2.可以不写在viewWillAppear中也可以满足push和pop不更改约束的问题
3.不对约束进行修改,修改的是layoutMargins,使其默认的20变成0,这样不影响导航栏中其他视图的约束冲突问题
4.代码量不重,和之前不通,这次仅仅是调整layoutMargins,不需要为了修改约束等再添加图层等,具体可以看我之前的,比较写法差异
5.最后代码也更加简洁.
@implementation UINavigationBar (SXFixSpace) +(void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self swizzleInstanceMethodWithOriginSel:@selector(layoutSubviews) swizzledSel:@selector(sx_layoutSubviews)]; }); } -(void)sx_layoutSubviews{ [self sx_layoutSubviews]; if (deviceVersion >= 11) { self.layoutMargins = UIEdgeInsetsZero; CGFloat space = sx_tempFixSpace !=0 ? sx_tempFixSpace : sx_defaultFixSpace; for (UIView *subview in self.subviews) { if ([NSStringFromClass(subview.class) containsString:@"ContentView"]) { subview.layoutMargins = UIEdgeInsetsMake(0, space, 0, space);//可修正iOS11之后的偏移 break; } } } } @end @implementation UINavigationItem (SXFixSpace) +(void)load { [self swizzleInstanceMethodWithOriginSel:@selector(setLeftBarButtonItem:) swizzledSel:@selector(sx_setLeftBarButtonItem:)]; [self swizzleInstanceMethodWithOriginSel:@selector(setLeftBarButtonItems:) swizzledSel:@selector(sx_setLeftBarButtonItems:)]; [self swizzleInstanceMethodWithOriginSel:@selector(setRightBarButtonItem:) swizzledSel:@selector(sx_setRightBarButtonItem:)]; [self swizzleInstanceMethodWithOriginSel:@selector(setRightBarButtonItems:) swizzledSel:@selector(sx_setRightBarButtonItems:)]; } -(void)sx_setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem { if (leftBarButtonItem.customView) { if (deviceVersion >= 11) { sx_tempFixSpace = 0; [self sx_setLeftBarButtonItem:leftBarButtonItem]; } else { [self setLeftBarButtonItems:@[leftBarButtonItem]]; } } else { sx_tempFixSpace = 20; [self sx_setLeftBarButtonItem:leftBarButtonItem]; } } -(void)sx_setLeftBarButtonItems:(NSArray<UIBarButtonItem *> *)leftBarButtonItems { NSMutableArray *items = [NSMutableArray arrayWithObject:[self fixedSpaceWithWidth:sx_defaultFixSpace-20]];//可修正iOS11之前的偏移 [items addObjectsFromArray:leftBarButtonItems]; [self sx_setLeftBarButtonItems:items]; } -(void)sx_setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem{ if (rightBarButtonItem.customView) { if (deviceVersion >= 11) { sx_tempFixSpace = 0; [self sx_setRightBarButtonItem:rightBarButtonItem]; } else { [self setRightBarButtonItems:@[rightBarButtonItem]]; } } else { sx_tempFixSpace = 20; [self sx_setRightBarButtonItem:rightBarButtonItem]; } } -(void)sx_setRightBarButtonItems:(NSArray<UIBarButtonItem *> *)rightBarButtonItems{ NSMutableArray *items = [NSMutableArray arrayWithObject:[self fixedSpaceWithWidth:sx_defaultFixSpace-20]];//可修正iOS11之前的偏移 [items addObjectsFromArray:rightBarButtonItems]; [self sx_setRightBarButtonItems:items]; } -(UIBarButtonItem *)fixedSpaceWithWidth:(CGFloat)width { UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; fixedSpace.width = width; return fixedSpace; } @end
效果和之前的解决方案几乎一样,只能说这次是换了思路实现的
可以很明显的看到间距不是20,至于是多少?
我用宏定义的方式设置的,你也可以自定义,或者使用其他的方式确定其大小
新的demo地址:
https://github.com/spicyShrimp/UINavigation-SXFixSpace
相关文章推荐
- [置顶] iOS11 导航栏按钮位置问题的解决
- iOS11 导航栏按钮位置问题的解决
- iOS11 完美解决导航栏按钮偏移问题 韩俊强的博客
- iOS11导航栏自定义按钮偏移问题
- 解决 ios7.0 以后自定义导航栏左边按钮靠右的问题
- 自定义导航栏左边按钮的位置靠左问题,右边按钮的位置靠右的问题
- 解决 ios7.0 以后自定义导航栏左边按钮靠右的问题
- ios11导航栏按钮不适配解决方法
- 关于iOS导航栏返回按钮问题的解决方法
- 解决导航栏返回按钮与Pop手势冲突的问题
- 解决ios7.0 以后自定义导航栏左边按钮靠右的问题
- iOS 解决导航栏左右 BarButtonItem偏移位置的问题
- iOS11中navigationBar上 按钮图片设置frame无效 不受约束 产生错位问题 解决
- 位置距离[置顶] 营救公主(Java实现A*算法解决迷宫问题)
- ios7以上,导航栏的按钮会出现向中间偏移问题的解决方法
- reportviewer 解决按钮tips英文问题
- 解决input按钮显示差异的问题
- netbeans下调试j2me,出现提示要tomcat的manager权限的用户名和密码问题解决位置
- 解决子元素margin让父辈元素位置一起改变的问题
- [置顶] fineuploader 跨子域上传文件 cookie丢失问题的解决