如何编辑 UINavigationBar [ iOS7]中左右 UIBarButtonItem 的空格

之前我用的是 iOS6.1,但现在我用的是 iOS7。除了其他问题之外,我还注意到在导航栏中,在 IOS 7中,左栏按钮项目的左边空间和右栏按钮项目的右边空间要比在 iOS 6中多得多。

我需要知道是否有一种方法可以减少导航栏中左右栏按钮项目的空白? ? ?

先谢谢你。

59349 次浏览

我相信您需要使用一个自定义按钮与 UIButton子类,并在您的子类,覆盖 -alignmentRectInsets。我忘记了你是否需要一个正面或负面的价值为适当的边缘得到它正确的转移,但如果一个不工作,尝试其他。

我也面临着这个问题。我也觉得 iOS7有更多的空间。然后我算出来,这大概多了10个百分点。当我想让 LeftBarItemButton从边缘开始时,我通常使用负空格。这对你也很有用。

UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];


negativeSpacer.width = -16; // it was -6 in iOS 6


[self.navigationItem setLeftBarButtonItems:@[negativeSpacer, requiredButton]; /* this will be the button which you actually need */] animated:NO];

为了修复这个错误,您必须继承 UIButton,这样才能重写 alignmentRectInsets。根据我的测试,您需要返回一个 UIEdgeInsets,根据按钮位置的不同,返回一个正的右偏移量或正的左偏移量。这些数字对我来说毫无意义(根据常识,其中至少有一个应该是负数) ,但这才是真正起作用的:

- (UIEdgeInsets)alignmentRectInsets {
UIEdgeInsets insets;
if (IF_ITS_A_LEFT_BUTTON) {
insets = UIEdgeInsetsMake(0, 9.0f, 0, 0);
}
else { // IF_ITS_A_RIGHT_BUTTON
insets = UIEdgeInsetsMake(0, 0, 0, 9.0f);
}
return insets;
}

特别感谢@zev 建议我尝试调整 alignmentRectInsets

基于@C _ X 他的回答,我创建了一个类别,根据当前设备的 iOS 版本添加和定位 UIBarButtonItem。

// UINavigationItem+Additions.h
@interface UINavigationItem (Additions)
- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem;
- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem;
@end


// UINavigationItem+Additions.m
@implementation UINavigationItem (Additions)


- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
// Add a negative spacer on iOS >= 7.0
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = -10;
[self setLeftBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, leftBarButtonItem, nil]];
} else {
// Just set the UIBarButtonItem as you would normally
[self setLeftBarButtonItem:leftBarButtonItem];
}
}


- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem
{
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) {
// Add a negative spacer on iOS >= 7.0
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = -10;
[self setRightBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, rightBarButtonItem, nil]];
} else {
// Just set the UIBarButtonItem as you would normally
[self setRightBarButtonItem:rightBarButtonItem];
}
}


@end

在视图控制器中,现在可以使用 [self.navigationItem addLeftBarButtonItem:leftBarButtonItem];[self.navigationItem addRightBarButtonItem:rightBarButtonItem];

我还尝试过子类化 UIButton并覆盖 -alignmentRectInsets,但这给我带来了视图之间转换的问题。

Smek 的线索之后,我创建了一个类别,但是对它进行了修改,以提供向后兼容性,而不是向前兼容。我把所有东西都设置成 iOS7中我想要的样子,然后如果用户运行的东西比较低,我就开始乱搞。

@interface UINavigationItem (BarButtonItemSpacingSupport)


- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem;
- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem;


@end


@implementation UINavigationItem (BarButtonItemSpacingSupport)


- (void)addLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem
{
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
// Add a spacer on when running lower than iOS 7.0
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = 10;
[self setLeftBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, leftBarButtonItem, nil]];
} else {
// Just set the UIBarButtonItem as you would normally
[self setLeftBarButtonItem:leftBarButtonItem];
}
}


- (void)addRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem
{
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
// Add a spacer on when running lower than iOS 7.0
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
negativeSpacer.width = 10;
[self setRightBarButtonItems:[NSArray arrayWithObjects:negativeSpacer, rightBarButtonItem, nil]];
} else {
// Just set the UIBarButtonItem as you would normally
[self setRightBarButtonItem:rightBarButtonItem];
}
}


@end

然后为了得到全局的结果,我有一个很薄的 UIViewController子类,所有的视图控制器都是从这个子类继承的。

@interface INFViewController : UIViewController


@end


@implementation INFViewController


- (void)viewDidLoad {
[super viewDidLoad];
if (SYSTEM_VERSION_LESS_THAN(@"7.0")) {
[self setupNavBarForPreIOS7Support];
}
}


- (void)setupNavBarForPreIOS7Support {
if (self.navigationController) {
UINavigationItem *navigationItem = self.navigationItem;
UIBarButtonItem *leftItem = navigationItem.leftBarButtonItem;
UIBarButtonItem *rightItem = navigationItem.rightBarButtonItem;


if (leftItem) {
[navigationItem addLeftBarButtonItem:leftItem];
}


if (rightItem) {
[navigationItem addRightBarButtonItem:rightItem];
}
}
}


@end

我意识到我正在检查操作系统版本两次(一次在 INFViewController中,另一次在类别中) ,我把它放在类别中,以防我想在项目的任何地方一次性使用它。

很好的决定,非常感谢! 我只需要在导航标题的左侧添加两个元素。 这是我的解决办法:

  // Settings Button
// This trick correct spacing between two left buttons
UIBarButtonItem *settingsButtonItem = [[UIBarButtonItem alloc] init];
UIView *settingsButtonItemView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 22.0, 22.0)];
settingsButtonItem.customView = settingsButtonItemView;
UIButton *settingsButton = [UIButton buttonWithType:UIButtonTypeSystem];
settingsButton.frame = settingsButtonItemView.frame;
[settingsButton setImage:[UIImage imageNamed:@"settings"] forState:UIControlStateNormal];
settingsButton.tintColor = [[[[UIApplication sharedApplication] delegate] window] tintColor];
[settingsButton addTarget:self action:@selector(showSettings:) forControlEvents:UIControlEventTouchDown];
[settingsButtonItemView addSubview:settingsButton];


// Star Button
UIBarButtonItem *starButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"star_gray"] style:UIBarButtonItemStyleBordered target:self action:@selector(showStarred)];
starButtonItem.width = 22.0;
NSLog(@"%f", starButtonItem.width);


// Negative Spacer
// It shifts star button to the left
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSpacer.width = -10.0;


NSArray *leftNavigtaionBarButtonItems = @[negativeSpacer, starButtonItem, settingsButtonItem];
[self.navigationItem setLeftBarButtonItems:leftNavigtaionBarButtonItems];

对于 Swift 2.0,这是我得到以下效果的解决方案..。

(实际值可能不同,取决于您的情况)

enter image description here

let captureButton = UIButton()
captureButton.setTitle("CAPTURE DETAILS", forState: .Normal)
captureButton.frame = CGRectMake(0, 0, 200, 95)
captureButton.addTarget(self, action: Selector("showCaptureDetailsForm:"), forControlEvents: .TouchUpInside) // *** See update below for Swift 2.2 syntax
captureButton.setBackgroundImage(UIImage(named: "blueTopRight"), forState: .Normal)
        

let rightBarButton = UIBarButtonItem()
rightBarButton.customView = captureButton
        

let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = -25;
        

self.navigationItem.setRightBarButtonItems([negativeSpacer, rightBarButton ], animated: false)

Swift 2.2更新:

对于 Swift 2.2,action: Selector方法已经更改,应该按以下方式键入

captureButton.addTarget(self, action: #selector(YourViewController.showCaptureDetailsForm(_:)), forControlEvents: .TouchUpInside)

因为你很快就能做到

var negativeSpace:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpace.width = -17.0
self.navigationItem.rightBarButtonItems = [negativeSpace, requiredButton /* this will be the button which you actually need */]

斯威夫特3:

let negativeSpacer:UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
negativeSpacer.width = -10
self.navigationItem.leftBarButtonItems = [negativeSpacer, yourBarButtonItem]

这是我对 Swift 3.0的解决方案:

rightBtn.imageInsets = UIEdgeInsets(top: 0, left: -13.0, bottom: 0, right: 13.0)
self.navigationItem.rightBarButtonItem = rightBtn

Swift 3.1

给左栏按钮项留下负空格:

    let backButton = UIButton.init(type: .custom)
backButton.frame = CGRect.init(x: 0, y: 0, width: 40, height: 40)
// negative space
backButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: -44.0, bottom: 0, right: 0)
backButton.setImage(Ionicons.iosArrowBack.image(30, color: UIColor(hex: 0xFD6250)), for: .normal)
backButton.addTarget(self, action: #selector(InviteVC.goBack), for: .touchUpInside)
// set back button
self.navigationItem.leftBarButtonIteUIBarButtonItem.init(customView: backButton)

As of iOS 11 wont accept negative space width, in order to align the bar button items to the margin, I have used the below code.


override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
for view in (self.navigationController?.navigationBar.subviews)! {
view.layoutMargins = UIEdgeInsets.zero
}
}

负空间在 iOS11上不起作用

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// to remove navigation bar extra margin
for view in (self.navigationController?.navigationBar.subviews)! {
view.layoutMargins = UIEdgeInsets.zero
}
}

上面的代码将从左边的 BarButtonItem 和右边的 BarButtonItem 中移除边距。如果您需要添加额外的页边距(删除页边距后) ,请添加以下代码

    let rightButton = UIButton(frame: CGRect(x: 0, y: 0, width: 17, height: 20))
rightButton.setImage(UIImage(named: "ic_cart"), for: .normal)


let rightBarButtomItem = UIBarButtonItem(customView: rightButton)


let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: nil, action: nil)
spacer.width = 28 //This will add extra margin on right side
navigationItem.rightBarButtonItems = [spacer,rightBarButtomItem]

对我有用

RightBarButton.customView? . transform = CGAffineTransform (translationX: 10,y: 0)