Як редагувати порожні пробіли лівого, правого UIBarButtonItem у UINavigationBar [iOS 7]


84

Я використовував iOS 6.1 раніше, але зараз я перейшов до iOS 7. Разом з іншими проблемами, я помітив, що на моїй навігаційній панелі лівий простір елемента кнопки лівої панелі та правий простір елемента правої панелі кнопок цілком більше в IOS 7, ніж в iOS 6.

Мені потрібно знати, чи є спосіб зменшити порожні пробіли елементів лівої та правої панелей панелі навігації ??

Заздалегідь спасибі.



@devxoul, UINavigationItem-Margin має проблему з iOS14. я створив проблему для цього, якщо у вас є якесь рішення, будь ласка, вивчіть це.
Кулдіп

Відповіді:


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, оскільки я зараз використовую це у своїх кількох проектах ... існує різниця в бальній системі, тому про це потрібно подбати ....
Аднан Афтаб

10
Це не працює, якщо ви робите [NSArray arrayWithObjects: requiredButton, negativeSpacer]. Слідкуйте за порядком.
Мерт Буран

3
Чудово працює, і зауважте, що для rightBarButtonItems розпірка повинна бути першим елементом масиву, якщо ви хочете змінити
правое

1
@C_X для iPhone 6, межа -16, схоже, не працює. -20 здається правильним .. Будь-яка ідея, як ми можемо зробити це нормально на всіх пристроях iPhone?
Vignesh PT,

1
@TheRohanSanap - додатна ширина буде розпіркою, яка збільшує кількість порожнього місця перед першим візуальним елементом. Цей фокус з від’ємною шириною зменшує порожній простір.
ToolmakerSteve

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)

Свіфт 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. Під час мого тестування вам потрібно буде повернути 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 6, вони запускалися в неправильному місці і переходили відповідно до вставок після завершення анімації.
Кріс Вагнер,

Я б не здивувався. Вищезазначений код потрібен лише для отримання макета стилю 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

Я усвідомлюю, що двічі перевіряю версію ОС (один раз 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
Рафікул Хасан,

4

Свіфт 3:

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

2

Свіфт 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
"Помилка клієнта при спробі змінити поля макета приватного перегляду"
Влад Пулічев,

0

Я вважаю, що вам потрібно використовувати спеціальну кнопку з UIButtonпідкласом, а у своєму підкласі замінити -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];
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.