Cómo editar espacios vacíos de Left, Right UIBarButtonItem en UINavigationBar

Estaba usando iOS 6.1 anteriormente, pero ahora me he movido a iOS 7. Junto con otros problemas, he observado que en mi barra de navegación, el espacio izquierdo del elemento del botón de la barra izquierda y el espacio vacío derecho del elemento del botón derecho del botón son bastante más en iOS 7 que en iOS 6.

Necesito saber si hay alguna manera de reducir los espacios vacíos de los ítems del botón de la barra izquierda, derecha en la barra de navegación?

Gracias por adelantado.

Yo también estaba enfrentando este problema. También tengo la sensación de que en iOS 7 hay más espacio. Y descubrí que esto es alrededor de 10 puntos más. Usualmente uso espacios negativos cuando quiero que LeftBarItemButton comience desde el borde. Esto puede ser útil para ti tambié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]; 

Basado en @C_X su respuesta, he creado una categoría que agrega y posiciona el UIBarButtonItem basado en la versión iOS del dispositivo actual.

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

En su controlador de vista ahora puede usar [self.navigationItem addLeftBarButtonItem:leftBarButtonItem]; y [self.navigationItem addRightBarButtonItem:rightBarButtonItem];

También intenté subclasificar UIButton y anular -alignmentRectInsets pero esto me dio problemas con las transiciones entre vistas.

Para Swift 2.0, esta fue mi solución para obtener el siguiente efecto …

(los valores reales pueden ser diferentes, dependiendo de su situación)

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 ACTUALIZACIÓN:

Para Swift 2.2, la action: Selector método action: Selector ha cambiado y debe escribirse de la siguiente manera

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

Para solucionar este error, debe subclase UIButton para que pueda anular alignmentRectInsets . A partir de mis pruebas, deberá devolver un UIEdgeInsets con un desplazamiento a la derecha positivo o un desplazamiento a la izquierda positivo, dependiendo de la posición del botón. Estos números no tienen sentido para mí (al menos uno de ellos debería ser negativo, de acuerdo con el sentido común), pero esto es lo que realmente funciona:

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

Un agradecimiento especial a @zev por sugerir que intente ajustar alignmentRectInsets .

Siguiendo el ejemplo de smek, hice una categoría pero la modifiqué para proporcionar compatibilidad hacia atrás en lugar de hacia adelante. Configuro todo para que funcione como lo quiero en iOS 7 y luego, si el usuario ejecuta algo más bajo, empiezo a perder cosas.

 @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 

Y luego para obtener esto globalmente, tengo una subclase UIViewController delgada de la que todos mis controladores de vista heredan.

 @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 

Me doy cuenta de que estoy verificando la versión del sistema operativo dos veces (una vez en INFViewController y nuevamente en la categoría), la dejé en la categoría en caso de que quiera utilizarla como una INFViewController única en cualquier parte del proyecto.

para swift puedes hacer esto

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

Swift 3:

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

Esta es mi solución para swift 3.0:

rightBtn.imageInsets = UIEdgeInsets (arriba: 0, izquierda: -13.0, abajo: 0, derecha: 13.0) self.navigationItem.rightBarButtonItem = rightBtn

Swift 3.1

Para dar espacio negativo al elemento del botón de la barra izquierda:

  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) 

Creo que necesita usar un botón personalizado con una subclase UIButton , y en su subclase, anular -alignmentRectInsets . Olvidé si necesita un valor positivo o negativo para el borde apropiado para que cambie correctamente, pero si uno no funciona, intente con el otro.

Buena decisión, muchas gracias! Necesitaba agregar solo dos elementos al lado izquierdo del encabezado de navegación. Esta es mi solución:

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