iOS11 导航栏按钮位置问题的解决

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
--------------------- 
作者:spicyShrimp 
来源:CSDN 
原文:https://blog.csdn.net/spicyShrimp/article/details/78201042 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值