美文网首页iOS菜鸟联盟
iOS 11 调整导航条按钮的位置失效了。

iOS 11 调整导航条按钮的位置失效了。

作者: 走向菜鸟的菜鸟 | 来源:发表于2018-03-09 18:47 被阅读87次

    借鉴大神的操作:picyShrimp

    项目需求:有一个界面UI的导航栏右侧按钮要紧靠右侧屏幕边缘,在iOS11以下系统采用UIBarButtonSystemItemFixedSpace方式没有问题,但是做iOS11适配时发现,UIBarButtonSystemItemFixedSpace方式无效了!导致右侧按钮和屏幕边缘出现大约20像素的间距!

    在iOS11系统之前,我想大部分iOS开发者调整UIBarButtonItem的位置的时候使用的大概都是UIBarButtonSystemItemFixedSpace方式:

    UIBarButtonItem *fixedSpace = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
    fixedSpace.width = width;
    [self.navigationItem setRightBarButtonItems:@[[UIBarButtonItem fixedSpaceWithWidth:-20], rightBarButtonItem]];
    

    iOS 11对导航栏的层级进行了修改,导致这种方式在iOS 11中失效了!
    具体解释不再赘述,直接上解决方法。
    我们需要做这样的一个分类,我想的是按钮添加在一个我们定义的view中,view作为customView,这样view作为一个位置调整的视图,就可以相对自由的定义位置了

    @implementation UINavigationItem (SXFixSpace)
    
    +(void)load {
        [self swizzleInstanceMethodWithOriginSel:@selector(setLeftBarButtonItem:)
                                     swizzledSel:@selector(sx_setLeftBarButtonItem:)];
        [self swizzleInstanceMethodWithOriginSel:@selector(setRightBarButtonItem:)
                                     swizzledSel:@selector(sx_setRightBarButtonItem:)];
    }
    
    -(void)sx_setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem{
        if (leftBarButtonItem.customView) {
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11) {
                UIView *customView = leftBarButtonItem.customView;
                BarView *barView = [[BarView alloc]initWithFrame:customView.bounds];
                [barView addSubview:customView];
                customView.center = barView.center;
                [barView setPosition:SXBarViewPositionLeft];
                [self setLeftBarButtonItems:nil];
                [self sx_setLeftBarButtonItem:[[UIBarButtonItem alloc]initWithCustomView:barView]];
            }else {
                [self sx_setLeftBarButtonItem:nil];
                [self setLeftBarButtonItems:@[[UIBarButtonItem fixedSpaceWithWidth:-20], leftBarButtonItem]];
            }
        }else {
            [self setLeftBarButtonItems:nil];
            [self sx_setLeftBarButtonItem:leftBarButtonItem];
        }
    }
    
    -(void)sx_setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem{
        if (rightBarButtonItem.customView) {
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 11) {
                UIView *customView = rightBarButtonItem.customView;
                BarView *barView = [[BarView alloc]initWithFrame:customView.bounds];
                [barView addSubview:customView];
                customView.center = barView.center;
                [barView setPosition:SXBarViewPositionRight];
                [self setRightBarButtonItems:nil];
                [self sx_setRightBarButtonItem:[[UIBarButtonItem alloc]initWithCustomView:barView]];
            } else {
                [self sx_setRightBarButtonItem:nil];
                [self setRightBarButtonItems:@[[UIBarButtonItem fixedSpaceWithWidth:-20], rightBarButtonItem]];
            }
        }else {
            [self setRightBarButtonItems:nil];
            [self sx_setRightBarButtonItem:rightBarButtonItem];
        }
    }
    
    @end
    

    在这个view中我们需要做这样的处理:就是遍历view的父视图,当其实UIStackView的时候,我们修改其左右约束,但是仅仅修改的话会造成约束冲突,所以我们还需要提前移除约束冲突的左右约束(如果担心影响问题,不移除没有关系,仅仅是编译器会报约束冲突log,代码洁癖的话会感觉不舒服)

    typedef NS_ENUM(NSInteger, SXBarViewPosition) {
        SXBarViewPositionLeft,
        SXBarViewPositionRight
    };
    
    @interface BarView : UIView
    @property (nonatomic, assign) SXBarViewPosition position;
    @property (nonatomic, assign) BOOL applied;
    @end
    
    @implementation BarView
    
    - (void)layoutSubviews {
        [super layoutSubviews];
        if (self.applied || [[[UIDevice currentDevice] systemVersion] floatValue]  < 11) return;
        UIView *view = self;
        while (![view isKindOfClass:UINavigationBar.class] && view.superview) {
            view = [view superview];
            if ([view isKindOfClass:UIStackView.class] && view.superview) {
                if (self.position == SXBarViewPositionLeft) {
                    for (NSLayoutConstraint *constraint in view.superview.constraints) {
                        if ([constraint.firstItem isKindOfClass:[UILayoutGuide class]] &&
                         constraint.firstAttribute == NSLayoutAttributeTrailing) {
                            [view.superview removeConstraint:constraint];
                        }
                    }
                    [view.superview addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                               attribute:NSLayoutAttributeLeading
                                                                               relatedBy:NSLayoutRelationEqual
                                                                                  toItem:view.superview
                                                                               attribute:NSLayoutAttributeLeading
                                                                              multiplier:1.0
                                                                                constant:0]];
                    self.applied = YES;
                } else if (self.position == SXBarViewPositionRight) {
                    for (NSLayoutConstraint *constraint in view.superview.constraints) {
                        if ([constraint.firstItem isKindOfClass:[UILayoutGuide class]] &&
                         constraint.firstAttribute == NSLayoutAttributeLeading) {
                            [view.superview removeConstraint:constraint];
                        }
                    }
                    [view.superview addConstraint:[NSLayoutConstraint constraintWithItem:view
                                                                               attribute:NSLayoutAttributeTrailing
                                                                               relatedBy:NSLayoutRelationEqual
                                                                                  toItem:view.superview
                                                                               attribute:NSLayoutAttributeTrailing
                                                                              multiplier:1.0
                                                                                constant:0]];
                    self.applied = YES;
                }
                break;
            }
        }
    }
    
    @end
    

    相关文章

      网友评论

        本文标题:iOS 11 调整导航条按钮的位置失效了。

        本文链接:https://www.haomeiwen.com/subject/vxjmfftx.html