¿Cómo muestro / oculto un UIBarButtonItem?


251

Creé una barra de herramientas en IB con varios botones. Me gustaría poder ocultar / mostrar uno de los botones dependiendo del estado de los datos en la ventana principal.

UIBarButtonItem no tiene una propiedad oculta, y los ejemplos que he encontrado hasta ahora para ocultarlos implican configurar los botones de la barra de navegación en cero, lo que no creo que quiera hacer aquí porque es posible que deba mostrar el botón nuevamente (no mencionar eso, si conecto mi botón a un IBOutlet, si lo configuro en cero, no estoy seguro de cómo recuperarlo).


Simplemente lo deshabilité y agregué una etiqueta de accesibilidad que decía que la función del botón no estaba disponible.
Daniel Springer el

Respuestas:


263

Guarde su botón en una salida fuerte (llamémoslo myButton) y haga esto para agregarlo / eliminarlo:

// Get the reference to the current toolbar buttons
NSMutableArray *toolbarButtons = [self.toolbarItems mutableCopy];

// This is how you remove the button from the toolbar and animate it
[toolbarButtons removeObject:self.myButton];
[self setToolbarItems:toolbarButtons animated:YES];

// This is how you add the button to the toolbar and animate it
if (![toolbarButtons containsObject:self.myButton]) {
    // The following line adds the object to the end of the array.  
    // If you want to add the button somewhere else, use the `insertObject:atIndex:` 
    // method instead of the `addObject` method.
    [toolbarButtons addObject:self.myButton];
    [self setToolbarItems:toolbarButtons animated:YES];
}

Debido a que está almacenado en la salida, mantendrá una referencia a él incluso cuando no esté en la barra de herramientas.


73
Para que esto funcione para mi botón derecho en un controlador de navegación, utilicé self.navigationItem.rightBarButtonItems y [self.navigationItem setRightBarButtonItems <prams>] en lugar de toolBarItems y setToolBarItems.
MindSpiker

@MindSpiker: Sí, la misma técnica también funciona para los botones en una barra de navegación.
lnafziger

1
¿Debo anular myButton en Dealloc?
Van Du Tran

49
O Apple podría haber agregado la propiedad .hidden. -_-
GeneCode

217

Sé que esta respuesta es tarde para esta pregunta. Sin embargo, podría ayudar si alguien más se enfrenta a una situación similar.

En iOS 7, para ocultar un elemento de botón de barra, podemos usar las dos técnicas siguientes:

  • uso SetTitleTextAttributes: - Esto funciona muy bien en elementos de botones de barra como "Listo", "Guardar", etc. Sin embargo, no funciona en elementos como Agregar, Símbolo de papelera, etc. (al menos no para mí) ya que no son textos.
  • uso TintColor: - Si tengo un elemento de botón de barra llamado "deleteButton": -

Para ocultar el botón, utilicé el siguiente código: -

[self.deleteButton setEnabled:NO]; 
[self.deleteButton setTintColor: [UIColor clearColor]];

Para mostrar el botón nuevamente utilicé el siguiente código: -

[self.deleteButton setEnabled:YES];
[self.deleteButton setTintColor:nil];

[self.navigationItem.rightBarButtonItem setEnabled: NO]; [self.navigationItem.rightBarButtonItem setTintColor: [UIColor clearColor]];
Leon

3
Para Swift: deleteButton.enabled = false; deleteButton.tintColor = UIColor.clearColor()para deshabilitar y ocultar, y deleteButton.enabled = true; deleteButton.tintColor = nilpara volver a habilitar y mostrar de forma normal.
Unixmonkey

1
Me gusta que este enfoque me permita poner la lógica para mostrar o no el UIBarButton dentro de esa clase. La razón por la que solo funciona con un botón no es obvia de inmediato: es porque si oculta un botón de esta manera, todavía ocupará espacio, por lo que es posible que tenga un espacio vacío si tiene varios botones.
SimplGy

Tu primer acercamiento fue perfecto para mí. Me puse UIColor.clearpara UIControlState.disabledy puedo mostrar / ocultar el botón con setEnabled. Por supuesto, como dijiste, esto solo funciona para los botones de texto.
fl034

Si lo presiono durante mucho tiempo hasta que aparezca en una imagen grande (probablemente para accesibilidad), incluso con isEnabled configurado en falso, todavía funciona.
Daniel Springer

67

Aquí hay un enfoque simple:

hide:  barbuttonItem.width = 0.01;
show:  barbuttonItem.width = 0; //(0 defaults to normal button width, which is the width of the text)

Acabo de ejecutarlo en mi iPad con retina y .01 es lo suficientemente pequeño como para que no aparezca.


13
De todas las soluciones, esta fue rápida, sucia y efectiva. También agregué barbuttItem.enabled = NO; ya que aún podría hacer que se disparara el botón si lo apretaba lo suficiente.
Stickley

1
No funciona para mi Pensé que era porque estaba usando un botón Agregar con la imagen '+', pero probé un botón Personalizado con el texto "Nuevo" y todavía no desaparece. La habilitación cambia, así que sé que mi código se está ejecutando. ¿Algunas ideas? Tenga en cuenta que este botón se crea en un guión gráfico y tiene una segue, por lo que no quiero cambiar a un botón programático
Ruibarbo

19
No parece funcionar en una barra de herramientas del controlador de navegación, pero lo hace para otras barras de herramientas.
Drew Rosenberg

3
Lo oculta pero aún responde a los grifos. Para mí, actúa como un botón invisible.
Tibidabo

Si ha establecido el color de tinte global utilizando esta línea self.window?.tintColor = APP_PRIMARY_COLORen applelegate, entonces esto no funcionará
Mehul Thakkar

60

Es posible ocultar un botón en su lugar sin cambiar su ancho o quitarlo de la barra. Si configura el estilo como simple, elimine el título y desactive el botón, desaparecerá. Para restaurarlo, simplemente invierta sus cambios.

-(void)toggleBarButton:(bool)show
{
    if (show) {
        btn.style = UIBarButtonItemStyleBordered;
        btn.enabled = true;
        btn.title = @"MyTitle";
    } else {
        btn.style = UIBarButtonItemStylePlain;
        btn.enabled = false;
        btn.title = nil;
    }
}

2
Esto funcionó para mí simplemente configurando btn.title = nil. También estoy configurando habilitado = NO, por si acaso ...
Pork 'n' Bunny

3
Establecer el buttonItem.title en nil no funcionó para mí en iOS7. El botón no volvió a aparecer al volver a configurarlo. Sin embargo, lo que funcionó fue configurar buttonItem.title = @ "";
Mark Knopper el

42

A continuación se muestra mi solución, aunque lo estaba buscando para la barra de navegación.

navBar.topItem.rightBarButtonItem = nil;

Aquí "navBar" es un IBOutlet para NavigationBar en la vista en XIB Aquí quería ocultar el botón o mostrarlo en función de alguna condición. Así que estoy probando la condición en "If" y si es verdadero, estoy configurando el botón en nil en el método viewDidLoad de la vista de destino.

Esto puede no ser relevante para su problema exactamente pero algo similar en caso de que desee ocultar botones en NavigationBar


Si desea volver a configurarlo rightBarButtonItemmás tarde , asegúrese de que el elemento del botón esté almacenado en un IBOutlet fuerte para que no se libere cuando lo retire de la barra de navegación.
Nate

30

Para Swift 3 y Swift 4 puede hacer esto para ocultar UIBarButtomItem:

self.deleteButton.isEnabled = false
self.deleteButton.tintColor = UIColor.clear

Y para mostrar el UIBarButtonItem:

self.deleteButton.isEnabled = true
self.deleteButton.tintColor = UIColor.blue

En el tintColordebe tener que especificar el color de origen que está utilizando para elUIBarButtomItem


2
Pero esto todavía tomará espacio para este botón.
Makalele

22

Actualmente estoy ejecutando OS X Yosemite Developer Preview 7 y Xcode 6 beta 6 dirigido a iOS 7.1 y la siguiente solución me funciona bien:

  • Crear salida para UINavigationItemy UIBarButtonItems
  • Ejecute el siguiente código para eliminar

    [self.navItem setRightBarButtonItem:nil];
    [self.navItem setLeftBarButtonItem:nil];
  • Ejecute los siguientes códigos para agregar botones nuevamente

    [self.navItem setRightBarButtonItem:deleteItem];
    [self.navItem setLeftBarButtonItem:addItem];

Gracias, este es el mejor método que he encontrado también. Solo asegúrate de que tus referencias a tus botones sean fuertes.
jyoung

Además, tenga en cuenta que esto solo funciona si tiene un solo botón allí. El ejemplo eliminará TODOS los botones de ese lado.
lnafziger

@jyoung Esto funcionó para mí, pero ¿por qué importa si la referencia es fuerte? No lo intenté de la otra manera, pero generalmente no lo configuro de esa manera, ya que no es el valor predeterminado.
Robert

@Robert Desea usar el objeto más adelante, por lo que debe asegurarse de que el objeto no se recolecte cuando se establece en cero. Si nada más retiene el objeto cuando le dice al elemento del botón de la barra que está bien deshacerse de él, su recuento de referencia sería 0 y sería recolección de basura.
jyoung

14

Usé IBOutlets en mi proyecto. Entonces mi solución fue:

@IBOutlet weak var addBarButton: UIBarButtonItem!

addBarButton.enabled = false
addBarButton.tintColor = UIColor.clearColor()

Y cuando necesite volver a mostrar esta barra, solo configure las propiedades invertidas.

En Swift 3, en cambio, enableuse la isEnablepropiedad.


13

self.dismissButton.customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];


12

iOS 8. UIBarButtonItem con imagen personalizada. Intenté muchas formas diferentes, la mayoría de ellas no estaban ayudando. La solución de Max, lasetTintColor no estaba cambiando a ningún color. Lo descubrí yo mismo, pensé que sería útil para alguien.

Para esconderse:

[self.navigationItem.rightBarButtonItem setEnabled:NO];
[self.navigationItem.rightBarButtonItem setImage:nil];

Para mostrar:

[self.navigationItem.rightBarButtonItem setEnabled:YES];
[self.navigationItem.rightBarButtonItem setImage:image];

9

Pruébelo en Swift , no actualice eltintColor si tiene algún diseño para su UIBarButtonItem como el tamaño de fuente en AppDelegate, cambiará totalmente la apariencia de su botón cuando aparezca.

En el caso de un botón de texto, cambiar el título puede hacer que su botón "desaparezca".

if WANT_TO_SHOW {
    myBarButtonItem.enabled = true
    myBarButtonItem.title = "BUTTON_NAME"
}else{
    myBarButtonItem.enabled = false
    myBarButtonItem.title = ""
}

7

Descubrí otra arruga en el tintColory el isEnabledenfoque sugerido por Max y otros - cuando VoiceOver está habilitado para la accesibilidad y el botón está lógicamente oculta, la accesibilidad del cursor todavía se centrará en el botón de la barra, y el estado que está "atenuado" (es decir, porque isEnabledes establecido en falso). El enfoque en la respuesta aceptada no sufre este efecto secundario, pero otra solución que encontré fue establecer isAccessibilityElementen falso al "ocultar" el botón:

deleteButton.tintColor = UIColor.clear
deleteButton.isEnabled = false
deleteButton.isAccessibilityElement = false

Y luego isAccessibilityElementvolviendo a verdadero cuando "muestra" el botón:

deleteButton.tintColor = UIColor.blue
deleteButton.isEnabled = true
deleteButton.isAccessibilityElement = true

El hecho de que el elemento del botón de la barra todavía ocupara espacio no fue un problema en mi caso, ya que estábamos ocultando / mostrando los elementos del botón de la barra más a la izquierda.


6
@IBDesignable class AttributedBarButtonItem: UIBarButtonItem {

    var isHidden: Bool = false {

        didSet {

            isEnabled = !isHidden
            tintColor = isHidden ? UIColor.clear : UIColor.black
        }
    }
}

Y ahora simplemente cambia de isHiddenpropiedad.


5

Mejorando desde la respuesta de @lnafziger

Guarde sus Barbuttons en una salida fuerte y haga esto para ocultarlo / mostrarlo:

-(void) hideBarButtonItem :(UIBarButtonItem *)myButton {
    // Get the reference to the current toolbar buttons
    NSMutableArray *navBarBtns = [self.navigationItem.rightBarButtonItems mutableCopy];

    // This is how you remove the button from the toolbar and animate it
    [navBarBtns removeObject:myButton];
    [self.navigationItem setRightBarButtonItems:navBarBtns animated:YES];
}


-(void) showBarButtonItem :(UIBarButtonItem *)myButton {
    // Get the reference to the current toolbar buttons
    NSMutableArray *navBarBtns = [self.navigationItem.rightBarButtonItems mutableCopy];

    // This is how you add the button to the toolbar and animate it
    if (![navBarBtns containsObject:myButton]) {
        [navBarBtns addObject:myButton];
        [self.navigationItem setRightBarButtonItems:navBarBtns animated:YES];
    }
}

Cuando sea necesario, use debajo de la función.

[self showBarButtonItem:self.rightBarBtn1];
[self hideBarButtonItem:self.rightBarBtn1];

5

Solo configura barButton.customView = UIView()y ve el truco


Lo que sí hace esta respuesta es permitir que todos los tamaños flexibles funcionen. En realidad es una respuesta súper eficiente. Probablemente, junto con una extensión, sería perfecto.
Adrian_H

4

No hay forma de "ocultar" un UIBarButtonItem, debe eliminarlo de la supervista y agregarlo nuevamente cuando desee volver a mostrarlo.


En realidad, esto no es cierto: el método descrito por Max funciona bien.
Northernman

1
nothernman: Max no es realmente correcto. En realidad, no está ocultando el botón de la forma en que la mayoría de la gente definiría "ocultar". Simplemente está haciendo que no sea visible e inhabilitando la interacción del usuario. El botón sigue ahí y ocupa espacio. Se trata de cómo quieres definir "ocultar", creo que el espíritu de la pregunta original era querer eliminarlo / agregarlo, no solo hacerlo invisible.
Michael Peterson el

4

Esto está muy por debajo de la lista de respuestas, pero en caso de que alguien quiera copiar y pegar fácilmente la solución rápida, aquí está

func hideToolbarItem(button: UIBarButtonItem, withToolbar toolbar: UIToolbar) {
    var toolbarButtons: [UIBarButtonItem] = toolbar.items!
    toolbarButtons.removeAtIndex(toolbarButtons.indexOf(button)!)
    toolbar.setItems(toolbarButtons, animated: true)
}

func showToolbarItem(button: UIBarButtonItem, inToolbar toolbar: UIToolbar, atIndex index: Int) {
    var toolbarButtons: [UIBarButtonItem] = toolbar.items!
    if !toolbarButtons.contains(button) {
        toolbarButtons.insert(button, atIndex: index)
        toolbar.setItems(toolbarButtons, animated:true);
    }
}

No está mal, pero debe dar un UINavigationItem como parámetro y no UIToolbar porque solicita ocultar un UIBarButtonItem. Modifiqué su función a esto: func hideToolbarItem (botón: UIBarButtonItem, withToolbar toolbar: UINavigationItem) {var toolbarButtons: [UIBarButtonItem] = toolbar.rightBarButtonItems! toolbarButtons.removeAtIndex (toolbarButtons.indexOf (button)!) toolbar.setRightBarButtonItems (toolbarButtons, animado: verdadero)} y eso funciona muy bien
Kingalione

3

Una forma de hacerlo es usar la initWithCustomView:(UIView *)propiedad de al asignar el UIBarButtonItem. La subclase para UIViewtendrá propiedades de ocultar / mostrar.

Por ejemplo:

1. Tener unUIButton que quiera ocultar / mostrar.

2. Haga el UIButtoncomo la vista personalizada. Me gusta :

UIButton*myButton=[UIButton buttonWithType:UIButtonTypeRoundedRect];//your button

UIBarButtonItem*yourBarButton=[[UIBarButtonItem alloc] initWithCustomView:myButton];

3. Puede ocultar / mostrar lo myButtonque ha creado.[myButton setHidden:YES];


Sin embargo, no cerrará la brecha entre los otros botones: cuando esté "oculto" habrá un área vacía en la barra de herramientas.
lnafziger

@lnafziger Sí, eso es cierto, pero no leí la mención de OP acerca de cerrar la brecha entre los botones, pero es un buen punto para tener en cuenta.
iNoob

1
Gracias, su respuesta también es útil, pero creo que la mayoría de las personas cuando quieren ocultar un botón en una barra de herramientas quieren que parezca que no está allí (sin el área en blanco). Si es el izquierdo o el derecho, realmente no importaría.
lnafziger

Buenos puntos, iNoob e Inafziger: no lo mencioné de ninguna manera, pero sí, preferiría que no hubiera un espacio en blanco.
Sasha

3

Para la versión Swift, aquí está el código:

Para UINavigationBar:

self.navigationItem.rightBarButtonItem = nil

self.navigationItem.leftBarButtonItem = nil

2

Establecer el color del texto en un color claro cuando el elemento del botón de la barra está desactivado es probablemente una opción más limpia. No hay rarezas que tengas que explicar en un comentario. Además, no destruye el botón, por lo que aún mantiene los segmentos asociados del guión gráfico.

[self.navigationItem.rightBarButtonItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor clearColor]}
                                                      forState:UIControlStateDisabled];

Luego, cuando quiera que se oculte el elemento del botón de la barra, puede hacer lo siguiente:

self.navigationItem.rightBarButton.enabled = NO;

Es lamentable que no haya propiedades ocultas, pero esto ofrece el mismo resultado.


1
Tenía un botón dentro del rightBarButtonItem. Así que configuré habilitado en NO y cambié su imagen en estado deshabilitado a nulo. Funcionó como un encanto ... Gracias
Skywalker

excelente idea, sin embargo, configurar la imagen como nula no funcionó para mí, tuve que poner un pequeño cuadrado transparente de 20x20 como imagen
Lena Bru

2

En caso de que el elemento UIBarButtonItem tenga una imagen en lugar del texto, puede hacer esto para ocultarlo: navigationBar.topItem.rightBarButtonItem.customView.alpha = 0.0;


2

Algunos métodos auxiliares que pensé que compartiría basados ​​en la respuesta aceptada de lnafziger ya que tengo múltiples barras de herramientas y múltiples botones en cada uno:

-(void) hideToolbarItem:(UIBarButtonItem*) button inToolbar:(UIToolbar*) toolbar{
    NSMutableArray *toolbarButtons = [toolbar.items mutableCopy];
    [toolbarButtons removeObject:button];
    [toolbar setItems:toolbarButtons animated:NO];
}

-(void) showToolbarItem:(UIBarButtonItem*) button inToolbar:(UIToolbar*) toolbar atIndex:(int) index{
    NSMutableArray *toolbarButtons = [toolbar.items mutableCopy];
    if (![toolbarButtons containsObject:button]){
        [toolbarButtons insertObject:button atIndex:index];
        [self setToolbarItems:toolbarButtons animated:YES];
    }
}

2

Puede obtener fácilmente la vista y ocultarla de esta manera

let view: UIView = barButtonItem.valueForKey("view") as! UIView
view.hidden = true

2

Si está usando Swift 3

if (ShowCondition){
   self.navigationItem.rightBarButtonItem = self.addAsset_btn 
 } 
else {
   self.navigationItem.rightBarButtonItem = nil
 }

2

Aquí hay una extensión que manejará esto.

extension UIBarButtonItem {

    var isHidden: Bool {
        get {
            return tintColor == .clear
        }
        set {
            tintColor = newValue ? .clear : .white //or whatever color you want
            isEnabled = !newValue
            isAccessibilityElement = !newValue
        }
    }

}

USO:

myBarButtonItem.isHidden = true

1

Complementando la respuesta de Eli Burke, si UIBarButtonItemtiene una imagen de fondo en lugar de un título, puede usar el código:

-(void)toggleLogoutButton:(bool)show{
    if (show) {
        self.tabButton.style = UIBarButtonItemStyleBordered;
        self.tabButton.enabled = true;
        UIImage* imageMap = [UIImage imageNamed:@"btn_img.png"];
        [((UIButton *)[self.tabButton customView]) setBackgroundImage:imageMap forState:UIControlStateNormal];
    } else {
        self.tabButton.style = UIBarButtonItemStylePlain;
        self.tabButton.enabled = false;
        [((UIButton *)[self.tabButton customView]) setBackgroundImage:nil forState:UIControlStateNormal];
    }
}

0

Necesita manipular la matriz toolbar.items.

Aquí hay un código que uso para ocultar y mostrar un botón Listo. Si su botón está en el borde extremo de la barra de herramientas o entre otros botones, sus otros botones se moverán, por lo que si desea que su botón simplemente desaparezca, coloque su botón como el último botón hacia el centro. Animé el movimiento del botón por efecto, me gusta bastante.

-(void)initLibraryToolbar {

    libraryToolbarDocumentManagementEnabled = [NSMutableArray   arrayWithCapacity:self.libraryToolbar.items.count];
    libraryToolbarDocumentManagementDisabled = [NSMutableArray arrayWithCapacity:self.libraryToolbar.items.count];
    [libraryToolbarDocumentManagementEnabled addObjectsFromArray:self.libraryToolbar.items];
    [libraryToolbarDocumentManagementDisabled addObjectsFromArray:self.libraryToolbar.items];
    trashCan = [libraryToolbarDocumentManagementDisabled objectAtIndex:3];
    mail = [libraryToolbarDocumentManagementDisabled objectAtIndex:5];
    [libraryToolbarDocumentManagementDisabled removeObjectAtIndex:1];
    trashCan.enabled = NO;
    mail.enabled = NO;
    [self.libraryToolbar setItems:libraryToolbarDocumentManagementDisabled animated:NO];

}

así que ahora puede usar el siguiente código para mostrar su botón

[self.libraryToolbar setItems:libraryToolbarDocumentManagementEnabled animated:YES];
trashCan.enabled = YES;
mail.enabled = YES; 

o para ocultar tu botón

[self.libraryToolbar setItems:libraryToolbarDocumentManagementDisabled animated:YES];
trashCan.enabled = NO;
mail.enabled = NO;

0

En IB, si deja el título del botón en blanco, no aparecerá (¿nunca inicializado?). Hago esto a menudo durante el desarrollo durante las actualizaciones de la interfaz de usuario si quiero que un elemento del botón de barra desaparezca temporalmente para una compilación sin eliminarlo y destruir todas sus referencias de salida.

Esto no tiene el mismo efecto durante el tiempo de ejecución, establecer el título del botón en cero no hará que desaparezca todo el botón. Lo sentimos, en realidad no responde a su pregunta, pero puede ser útil para algunos.

Editar: este truco solo funciona si el estilo del botón está configurado en plano


0

Agregaré mi solución aquí ya que no pude encontrarla mencionada aquí todavía. Tengo un botón dinámico cuya imagen depende del estado de un control. La solución más simple para mí fue establecer la imagen nilsi el control no estaba presente. La imagen se actualizaba cada vez que se actualizaba el control y, por lo tanto, esto era óptimo para mí. Sólo para estar seguro de que también puse el enabledque NO.

Establecer el ancho en un valor mínimo no funcionó en iOS 7.


0

Con crédito a @lnafziger, @MindSpiker, @vishal, et. Alabama,

El revestimiento más simple al que llegué para un solo botón de barra derecho (o izquierdo) es:

self.navigationItem.rightBarButtonItem = <#StateExpression#>
    ? <#StrongPropertyButton#> : nil;

Como en:

@interface MyClass()

@property (strong, nonatomic) IBOutlet UIBarButtonItem *<#StrongPropertyButton#>;

@end

@implementation

- (void) updateState
{
    self.navigationItem.rightBarButtonItem = <#StateExpression#>
        ? <#StrongPropertyButton#> : nil;
}

@end

Probé esto y funciona para mí (con el elemento de botón de barra fuerte conectado a través de IB).


Esto funcionará si solo tiene un botón, pero si tiene varios botones necesitará usar un método más similar a mi respuesta.
lnafziger
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.