2017-08-07 74 views
15

在iOS系统10和下面,有一个负间隔添加到按钮阵列中的导航栏,像这样的方式:为的UIBarButtonItem负间隔在导航栏上的iOS 11

UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 
negativeSpacer.width = -8; 
self.navigationItem.leftBarButtonItems = @[negativeSpacer, [self backButtonItem]]; 

此不再适用于iOS 11(间隔变为正值,而不是负值)。我检查了酒吧按钮项的视图层次结构,现在它嵌入到_UIButtonBarStackView中。如何调整iOS 11上的酒吧按钮的位置?

回答

5

我发现苹果开发者论坛有点哈克解决方案: https://forums.developer.apple.com/thread/80075

它看起来像问题来自于iOS的11如何处理UIBarButtonItem.fixedSpace按钮和一个UINavigationBar如何在iOS的11导航布局酒吧现在使用自动布局和布局边距来布置按钮。该帖子(底部)中提出的解决方案是将所有布局页边距设置为您想要的某个值。

class InsetButtonsNavigationBar: UINavigationBar { 

    override func layoutSubviews() { 
     super.layoutSubviews() 

     for view in subviews { 
      // Setting the layout margins to 0 lines the bar buttons items up at 
      // the edges of the screen. You can set this to any number to change 
      // the spacing. 
      view.layoutMargins = .zero 
     } 
    } 

} 

使用带有自定义按钮间距这种新的导航栏,你将需要更新,你用下面的代码创建任何导航控制器:

let navController = UINavigationController(navigationBarClass: InsetButtonsNavigationBar.self, 
               toolbarClass: UIToolbar.self) 
navController.viewControllers = [yourRootViewController] 
+0

不知道这与iPhone X横幅上的扩展空间很好地搭配。 – GuillermoMP

+0

我希望有另一种处理这种方式..我的应用程序中有太多的导航控制器,为他们每个人设置自定义导航栏将是相当乏味的。如果没有其他选择,我会接受这个答案。 – pckill

+0

@GuillermoMP,在iPhone X上,左右页边距设置为零后从64改为44,所以这里可能没有问题。编辑:第二个想法,如果你真的*想让你的按钮触摸屏幕的边缘,即使在风景中,也是一个巨大的问题。我有一个只有肖像的应用程序,所以一开始没有想到。 – pckill

1

基于keithbhunter的答案,我已经创建了一个定制UINavigationBar的:

NavigationBarCustomMargins.h:

#import <UIKit/UIKit.h> 

@interface NavigationBarCustomMargins : UINavigationBar 

@property (nonatomic) IBInspectable CGFloat leftMargin; 
@property (nonatomic) IBInspectable CGFloat rightMargin; 

@end 

NavigationBarCustomMargins.m:

#import "NavigationBarCustomMargins.h" 

#define DefaultMargin 16 
#define NegativeSpacerTag 87236223 

@interface NavigationBarCustomMargins() 

@property (nonatomic) BOOL leftMarginIsSet; 
@property (nonatomic) BOOL rightMarginIsSet; 

@end 

@implementation NavigationBarCustomMargins 

@synthesize leftMargin = _leftMargin; 
@synthesize rightMargin = _rightMargin; 

- (void)layoutSubviews { 
    [super layoutSubviews]; 

    if (([[[UIDevice currentDevice] systemVersion] compare:@"11.0" options:NSNumericSearch] != NSOrderedAscending)) { 
     BOOL isRTL = [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft; 
     for (UIView *view in self.subviews) { 
      view.layoutMargins = UIEdgeInsetsMake(0, isRTL ? self.rightMargin : self.leftMargin, 0, isRTL ? self.leftMargin : self.rightMargin); 
     } 
    } else { 
     //left 
     NSMutableArray *leftItems = [self.topItem.leftBarButtonItems mutableCopy]; 
     if (((UIBarButtonItem *)leftItems.firstObject).tag != NegativeSpacerTag) { 

      UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 
      negativeSpacer.tag = NegativeSpacerTag; 
      negativeSpacer.width = self.leftMargin - DefaultMargin; 
      [leftItems insertObject:negativeSpacer atIndex:0]; 

      [self.topItem setLeftBarButtonItems:[leftItems copy] animated:NO]; 
     } 

     //right 
     NSMutableArray *rightItems = [self.topItem.rightBarButtonItems mutableCopy]; 
     if (((UIBarButtonItem *)rightItems.firstObject).tag != NegativeSpacerTag) { 

      UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 
      negativeSpacer.tag = NegativeSpacerTag; 
      negativeSpacer.width = self.rightMargin - DefaultMargin; 
      [rightItems insertObject:negativeSpacer atIndex:0]; 
      [self.topItem setRightBarButtonItems:[rightItems copy] animated:NO]; 
     } 
    } 
} 

- (CGFloat)leftMargin { 
    if (_leftMarginIsSet) { 
     return _leftMargin; 
    } 
    return DefaultMargin; 
} 

- (CGFloat)rightMargin { 
    if (_rightMarginIsSet) { 
     return _rightMargin; 
    } 
    return DefaultMargin; 
} 

- (void)setLeftMargin:(CGFloat)leftMargin { 
    _leftMargin = leftMargin; 
    _leftMarginIsSet = YES; 
} 

- (void)setRightMargin:(CGFloat)rightMargin { 
    _rightMargin = rightMargin; 
    _rightMarginIsSet = YES; 
} 

@end 

之后,我设置自定义类来我在Interface Builder的UINavigationController,只是需要设置页边距: Screenshot 1

工作正常。支持RTL和iOS优先11: Screenshot 2

+0

我想你需要添加 '[自setNeedsLayout];' 为了setLeftMargin的底部:和setRightMargin: 这样,layoutSubviews将在下一个可用的机会中被更新的边界参数调用 – Chilly

1

只是我的情况的解决方法,它可能会对某些人有所帮助。我想实现这一点:

enter image description here 和以前我也使用negativeSpacer。现在我想通了这个解决方案:

 let logoImage = UIImage(named: "your_image") 
     let logoImageView = UIImageView(image: logoImage) 
     logoImageView.frame = CGRect(x: -16, y: 0, width: 150, height: 44) 
     logoImageView.contentMode = .scaleAspectFit 
     let logoView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 44)) 
     **logoView.clipsToBounds = false** 
     logoView.addSubview(logoImageView) 
     let logoItem = UIBarButtonItem(customView: logoView) 
     navigationItem.leftBarButtonItem = logoItem 
+0

该解决方案的触摸区域是什么?如果您点击视图左侧的所有方式,它是否会注册一个联系人? – keithbhunter

+0

@keithbhunter不幸的是,触摸区域只是logoView而不是logoImageView。 –