借鉴大神的操作: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
网友评论