วิธีแก้ไขช่องว่างของ UIBarButtonItem ซ้ายและขวาใน UINavigationBar [iOS 7]


84

ฉันใช้ iOS 6.1 ก่อนหน้านี้ แต่ตอนนี้ฉันได้ย้ายไปที่ iOS 7 แล้วพร้อมกับปัญหาอื่น ๆ ฉันสังเกตเห็นว่าในแถบนำทางพื้นที่ด้านซ้ายของรายการปุ่มแถบด้านซ้ายและพื้นที่ว่างด้านขวาของรายการแถบปุ่มด้านขวาค่อนข้างมาก ใน IOS 7 มากกว่า iOS 6

ฉันต้องการทราบว่ามีวิธีใดบ้างที่ฉันสามารถลดพื้นที่ว่างของรายการปุ่มแถบซ้ายและขวาในแถบนำทางได้หรือไม่?

ขอบคุณล่วงหน้า.


2
ลองสิ่งนี้: github.com/devxoul/UINavigationItem-Margin
devxoul

@devxoul, UINavigationItem-Margin มีปัญหากับ iOS14 ฉันได้สร้างปัญหาสำหรับสิ่งนั้นหากคุณมีวิธีแก้ไขโปรดตรวจสอบสิ่งนี้
Kuldeep

คำตอบ:


222

ฉันก็ประสบปัญหานี้เช่นกัน ฉันยังมีความรู้สึกว่าใน iOS 7 มีพื้นที่มากขึ้น และฉันพบว่านี่คืออีกประมาณ 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];

4
มันใช้งานได้จริงใน iOS 7 ขณะที่ฉันใช้สิ่งนี้ในสองโปรเจ็กต์ของฉันตอนนี้ ... มีความแตกต่างในระบบจุดดังนั้นคุณต้องดูแลเรื่องนั้น ....
Adnan Aftab

10
จะใช้ไม่ได้ถ้าคุณทำ [NSArray arrayWithObjects: requiredButton, negativeSpacer] คำนึงถึงคำสั่งซื้อ
บูรณ

3
ใช้งานได้ดีและโปรดทราบว่าสำหรับ rightBarButtonItems ตัวเว้นวรรคต้องเป็นรายการแรกในอาร์เรย์หากคุณต้องการเปลี่ยนระยะขอบด้านขวา
leonaka

1
@C_X สำหรับ iPhone 6 ระยะขอบ -16 ดูเหมือนจะไม่ทำงาน -20 ดูเหมือนถูกแล้ว .. มีความคิดยังไงว่าเราจะทำให้มันทำงานได้ดีในทุกอุปกรณ์ iPhone?
Vignesh PT

2
ไม่ทำงานสำหรับ iOS 13! มีใครรู้วิธีทำสิ่งนี้ใน iOS 13 บ้าง?
กุ

23

จากคำตอบของ @C_X ฉันได้สร้างหมวดหมู่ที่เพิ่มและวางตำแหน่ง UIBarButtonItem ตามเวอร์ชัน iOS ของอุปกรณ์ปัจจุบัน

// 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แต่สิ่งนี้ทำให้ฉันมีปัญหากับการเปลี่ยนระหว่างมุมมอง


10

สำหรับ Swift 2.0 นี่เป็นวิธีแก้ปัญหาของฉันที่จะได้รับผลต่อไปนี้ ...

(ค่าจริงอาจแตกต่างกันขึ้นอยู่กับสถานการณ์ของคุณ)

ใส่คำอธิบายภาพที่นี่

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)


9

นี่คือทางออกของฉันสำหรับSwift 3.0:

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

6

ในการแก้ไขข้อบกพร่องนี้คุณต้องคลาสย่อยUIButtonจึงจะสามารถลบล้างalignmentRectInsetsได้ จากการทดสอบของฉันคุณจะต้องส่งคืน a 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 เพราะตอนนี้ฉันกำลังพยายามหลีกเลี่ยงการแบ่งประเภทย่อย ..
Salman Zaidi

สิ่งนี้ทำให้ฉันมีการเปลี่ยนปุ่มแปลก ๆ ในระหว่างการเคลื่อนไหวใน iOS 6 พวกเขาจะเริ่มทำงานผิดจุดและเปลี่ยนไปให้ตรงกับสิ่งที่ใส่เข้าไปหลังจากภาพเคลื่อนไหวเสร็จสิ้น
Chris Wagner

ฉันคงไม่แปลกใจ จำเป็นต้องใช้โค้ดด้านบนเพื่อรับเลย์เอาต์สไตล์ iOS 6 สำหรับบิวด์ iOS 7 เท่านั้น
jaredsinclair

แก้ไขด่วนงานดี อย่างไรก็ตามสำหรับ iOS 9 คุณต้องส่งคืนสิ่งที่ใส่เข้าไปไม่ได้ตั้งค่าไว้:
A-Majeed

5

ต่อไปนี้นำ smek ของฉันทำหมวดหมู่ แต่มีการปรับเปลี่ยนให้มันเพื่อให้ทำงานร่วมกันหลังไปข้างหน้ามากกว่า ฉันตั้งค่าทุกอย่างให้ทำงานตามที่ฉันต้องการใน iOS 7 จากนั้นหากผู้ใช้ทำงานต่ำกว่าฉันก็เริ่มยุ่งกับสิ่งต่างๆ

@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

ฉันรู้ว่าฉันกำลังตรวจสอบเวอร์ชัน OS สองครั้ง (หนึ่งครั้งใน INFViewControllerแล้วครั้งเล่าในหมวดหมู่) ฉันทิ้งไว้ในหมวดหมู่ในกรณีที่ฉันต้องการใช้สิ่งนี้เป็นครั้งเดียวในทุกที่ในโครงการ


5

เพื่อความรวดเร็วคุณสามารถทำได้

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
วิธีนี้เรียกว่าล่าช้า
orium

นี่เป็นวิธีแก้ปัญหาที่ถูกต้องในการทำเช่นนี้พื้นที่เชิงลบจะไม่ทำงานจาก 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

ในการเพิ่มพื้นที่เชิงลบของรายการปุ่มแถบซ้าย:

    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

พื้นที่ว่างจะไม่ทำงานจาก iOS 11

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

โค้ดด้านบนจะลบระยะขอบจากทั้งสองด้าน leftBarButtonItem และ RightBarButtonItem หากคุณต้องการเพิ่มระยะขอบพิเศษ (หลังจากลบขอบ) ให้เพิ่มรหัสต่อไปนี้

    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
'ข้อผิดพลาดของไคลเอ็นต์ที่พยายามเปลี่ยนระยะขอบเลย์เอาต์ของมุมมองส่วนตัว'
Vlad Pulichev

0

ผมเชื่อว่าคุณต้องใช้ปุ่มที่กำหนดเองที่มีUIButtonคลาสย่อยและใน subclass -alignmentRectInsetsของคุณแทนที่ ฉันลืมว่าคุณต้องการค่าบวกหรือลบสำหรับขอบที่เหมาะสมเพื่อให้เปลี่ยนได้อย่างถูกต้อง แต่ถ้าไม่ได้ผลให้ลองใช้ค่าอื่น



-1

การตัดสินใจที่ดีขอบคุณมาก! ฉันต้องการเพิ่มเพียงสององค์ประกอบที่ด้านซ้ายของส่วนหัวการนำทาง นี่คือทางออกของฉัน:

  // 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];
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.