Cách chỉnh sửa Khoảng trống của UIBarButtonItem trái, phải trong UINavigationBar [iOS 7]


84

Tôi đã sử dụng iOS 6.1 trước đó, nhưng bây giờ tôi đã chuyển sang iOS 7. Cùng với các vấn đề khác, tôi đã quan sát thấy rằng trong thanh điều hướng của mình, khoảng trống bên trái của mục nút thanh bên trái và không gian trống bên phải của mục thanh nút bên phải khá nhiều hơn trong iOS 7 so với iOS 6.

Tôi cần biết là có cách nào tôi có thể giảm khoảng trống của các mục nút thanh bên trái, bên phải trong thanh điều hướng không ??

Cảm ơn trước.



@devxoul, UINavigationItem-Margin có vấn đề với iOS14. Tôi đã tạo ra vấn đề cho điều đó nếu bạn có bất kỳ giải pháp nào thì vui lòng xem xét vấn đề này.
Kuldeep

Câu trả lời:


222

Tôi cũng đang đối mặt với vấn đề này. Tôi cũng có cảm giác rằng trong iOS 7 có nhiều không gian hơn. Và tôi nhận ra rằng đây là khoảng hơn 10 điểm. Tôi thường sử dụng dấu cách âm khi tôi muốn LeftBarItemButtonbắt đầu từ rìa. Điều này cũng có thể hữu ích cho bạn.

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];

4
Nó thực sự làm việc trong iOS 7, khi tôi đang sử dụng này trong vài của tôi về dự án ngay bây giờ ... có sự khác biệt trong hệ thống điểm vì vậy bạn phải chăm sóc mà ....
Adnan Aftab

10
Nó không hoạt động nếu bạn thực hiện [NSArray arrayWithObjects: requiredButton, negativeSpacer]. Nhớ thứ tự.
Mert Buran

3
Các công trình lớn, và lưu ý rằng cho rightBarButtonItems các spacer phải là mục đầu tiên trong mảng nếu bạn muốn thay đổi lề phải
leonaka

1
@C_X cho iPhone 6, biên độ -16 dường như không hoạt động. -20 có vẻ đúng .. Bất kỳ ý tưởng nào về cách chúng tôi có thể làm cho điều này hoạt động tốt trên tất cả các thiết bị iPhone?
Vignesh PT

1
@TheRohanSanap - chiều rộng dương sẽ là khoảng đệm làm tăng bao nhiêu không gian trống trước mục trực quan đầu tiên. Thủ thuật chiều rộng âm này làm giảm không gian trống.
ToolmakerSteve

23

Dựa trên @C_X câu trả lời của anh ấy, tôi đã tạo một danh mục để thêm và định vị UIBarButtonItem dựa trên phiên bản iOS của thiết bị hiện tại.

// 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

Trong bộ điều khiển chế độ xem của bạn, bây giờ bạn có thể sử dụng [self.navigationItem addLeftBarButtonItem:leftBarButtonItem];[self.navigationItem addRightBarButtonItem:rightBarButtonItem];

Tôi cũng đã thử phân lớp con UIButtonvà ghi đè -alignmentRectInsetsnhưng điều này khiến tôi gặp vấn đề với việc chuyển đổi giữa các chế độ xem.


10

Đối với Swift 2.0, đây là giải pháp của tôi để đạt được hiệu quả sau ...

(các giá trị thực tế có thể khác nhau, tùy thuộc vào tình huống của bạn)

nhập mô tả hình ảnh ở đây

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)

CẬP NHẬT Swift 2.2:

Đối với Swift 2.2, action: Selectorphương thức đã thay đổi và sẽ được nhập như sau

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


9

Đây là giải pháp của tôi cho Swift 3.0:

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

6

Để sửa lỗi này, bạn phải phân lớp UIButtonđể bạn có thể ghi đè alignmentRectInsets. Từ thử nghiệm của tôi, bạn sẽ cần trả về a UIEdgeInsetscó độ lệch bên phải dương hoặc độ lệch bên trái dương, tùy thuộc vào vị trí nút. Những con số này không có ý nghĩa gì đối với tôi (ít nhất một trong số chúng phải là số âm, theo lẽ thường), nhưng đây là những gì thực sự hoạt động:

- (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;
}

Đặc biệt cảm ơn @zev đã đề xuất tôi thử điều chỉnh alignmentRectInsets.


cảm ơn vì câu trả lời. Mặc dù đó là một giải pháp tốt nhưng tôi có câu trả lời @C_X ưa thích vì ngay bây giờ tôi đang cố gắng để tránh phụ classing ..
Salman Zaidi

Điều này gây ra cho tôi một số chuyển đổi kỳ lạ của các nút trong hoạt ảnh trong iOS 6, chúng sẽ bắt đầu ở sai vị trí và dịch chuyển để khớp với nội dung sau khi hoạt ảnh hoàn thành.
Chris Wagner

Tôi sẽ không ngạc nhiên. Đoạn mã trên chỉ cần thiết để có được bố cục kiểu iOS 6 cho các bản dựng iOS 7.
jaredsinclair

Sửa chữa nhanh, công việc tốt. Tuy nhiên đối với iOS 9, bạn cần phải trả lại insets không cài đặt chúng:
A-Majeed

5

Theo hướng dẫn của smek, tôi đã tạo một danh mục nhưng sửa đổi nó để cung cấp khả năng tương thích ngược hơn là chuyển tiếp. Tôi thiết lập mọi thứ để hoạt động theo cách tôi muốn trong iOS 7 và sau đó nếu người dùng đang chạy thứ gì đó thấp hơn, tôi bắt đầu làm việc với mọi thứ.

@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

Và sau đó để có được điều này trên toàn cầu, tôi có một UIViewControllerlớp con mỏng mà tất cả các bộ điều khiển chế độ xem của tôi đều kế thừa.

@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

Tôi nhận ra rằng tôi đang kiểm tra phiên bản hệ điều hành hai lần (một lần INFViewControllervà một lần nữa trong danh mục), tôi đã để nó trong danh mục trong trường hợp tôi muốn sử dụng phiên bản này như một lần duy nhất ở bất kỳ đâu trong dự án.


5

nhanh chóng bạn có thể làm điều này

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 */]

5
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
                }
            }

2
phương pháp này được gọi với độ trễ
orium

Đây là giải pháp chính xác để làm điều này, không gian tiêu cực sẽ không hoạt động từ iOS 11
Rafiqul Hasan

4

Swift 3:

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

2

Swift 3.1

Để cung cấp cho mục nút thanh bên trái không gian âm:

    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) 


1

Negetive space sẽ không hoạt động từ iOS 11

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

Đoạn mã trên sẽ loại bỏ lề ở cả hai bên leftBarButtonItem và RightBarButtonItem. Nếu bạn cần thêm lề thừa (Sau khi loại bỏ lề), hãy thêm mã sau

    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]

1
'Lỗi ứng dụng khách khi cố gắng thay đổi lề bố cục của chế độ xem riêng tư'
Vlad Pulichev

0

Tôi tin rằng bạn cần sử dụng nút tùy chỉnh với UIButtonlớp con và trong lớp con của bạn, ghi đè -alignmentRectInsets. Tôi quên rằng bạn cần một giá trị dương hay âm cho cạnh thích hợp để làm cho nó dịch chuyển một cách chính xác, nhưng nếu một cái không hoạt động, hãy thử cái kia.


0

đã làm cho tôi

rightBarButton.customView? .transform = CGAffineTransform (dịchX: 10, y: 0)


-1

Quyết định tốt đẹp, cảm ơn rất nhiều! Tôi chỉ cần thêm hai phần tử vào bên trái của tiêu đề điều hướng. Đây là giải pháp của tôi:

  // 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];
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.