¿Texto personalizado del "botón de retroceso" de UINavigationController?


147

El "botón de retroceso" de un UINavigationControllerpor defecto muestra el título de la última vista en la pila. ¿Hay alguna forma de tener texto personalizado en el botón de retroceso?


1
Esto funciona para míself.navigationController.navigationBar.topItem.title = @"Custom text";
huync

Respuestas:


342

Desde este enlace :

self.navigationItem.backBarButtonItem =
   [[UIBarButtonItem alloc] initWithTitle:@"Custom Title"
            style:UIBarButtonItemStylePlain
           target:nil
           action:nil];

Como dijo Tyler en los comentarios:

no haga esto en el controlador de vista visible, sino en el controlador de vista que vería si presiona el botón Atrás


44
Deberías releaseel UIBarButtonItem.
Mehrdad Afshari

217
También tenga en cuenta que debe hacer esto en el controlador de vista un nivel más arriba en la pila. En otras palabras, no haga esto en el controlador de vista visible, sino en el controlador de vista que vería si presiona el botón Atrás.
Tyler

66
Solo para aclarar el comentario de Tyler porque no entendí esto al principio: configurar el elemento backBarButtonItem en un controlador de vista navigationItem es configurar el botón que se mostrará para VOLVER a este controlador de vista. También tenga en cuenta que, aunque no hay un estilo de botón para el botón de flecha, este botón obtendrá el estilo de flecha de todos modos. He usado UIBarButtonItemStylePlain y todavía obtengo el estilo del botón de flecha.
Jon Steinmetz

3
Sugerencia: en lugar de asumir el estilo, pase el estilo establecido actualmente. En el código de esta respuesta, reemplace UIBarButtonItemStyleBorderedcon una llamada a la propiedad self.navigationItem.backBarButtonItem.style. Documentación: developer.apple.com/library/ios/documentation/uikit/reference/…
Basil Bourque

1
Tenga en cuenta que bajo ARC debe omitir la llamada de liberación automática. entonces tiene self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @ Estilo "Título personalizado": UIBarButtonItemStyleBordered target: nil action: nil];
bkbeachlabs

43

Puede configurar el texto en el Creador de interfaces:

Seleccione el elemento de navegación del ViewController al que volvería el botón Atrás:

ingrese la descripción de la imagen aquí

En el inspector de atributos del panel de utilidades, ingrese su etiqueta para el Botón Atrás:

ingrese la descripción de la imagen aquí

Preferiría este enfoque en lugar de establecer el título en código como en la respuesta aceptada.

También tenga en cuenta que debe hacer esto en el controlador de vista un nivel más arriba en la pila. En otras palabras, no haga esto en el controlador de vista visible, sino en el controlador de vista que vería si presiona el botón Atrás.
--Tyler


Esta es la mejor respuesta que encontré hasta ahora.
Ayan Sengupta

2
Para que quede claro, esto debe establecerse en el elemento de navegación del controlador de vista, no en el inspector de atributos del controlador de vista en sí.
Patrick leyó el

Esta es la mejor respuesta que encontré.
bicepjai

Esta es la mejor respuesta
Alex Brown, el

2
A partir de Xcode 6.1.1, y ejecutándose en iOS 7, parece que su título de vista anterior original TODAVÍA anulará cualquier título de botón de retroceso que establezca aquí. Si el título de la vista anterior contiene más del límite de 11 caracteres, el botón de retroceso de la vista siguiente simplemente dirá "Atrás". No hay forma de evitarlo, excepto crear un nuevo elemento de barra de navegación desde cero como se muestra en la respuesta más votada aquí.
Ray

22

Yo uso esto:

// In the current view controller, not the one that is one level up in the stack
- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationController.navigationBar.backItem.title = @"Custom text";
}

Esto casi funciona para mí, pero cuando hago clic en el botón Atrás, el texto vuelve a cambiar al título del padre durante la duración de la animación :-(
Danny Tuppeny

3
Esto cambia el título del botón Atrás del controlador en la pila. No cambia el título del botón Atrás del controlador que se muestra actualmente. Peor aún: ¡cambia el título del controlador anterior al controlador anterior!
leviatán

Como señalaron otros comentaristas, este método es un poco insostenible. No recomendaría hacer esto, ya que no es realmente cómo la API pretende que lo uses. ¡Podría estar preparándose para errores difíciles en el futuro!
RickDT

11

Encontré una solución práctica para esto simplemente configurando el título del controlador antes de insertar otro controlador en la pila, de esta manera:

self.navigationItem.title = @"Replacement Title";
[self.navigationController pushViewController:newCtrl animated:YES];

Luego, asegúrate de establecer el título original de viewWillAppearesta manera:

-(void)viewWillAppear:(BOOL)animated
{
  ...
  self.navigationItem.title = @"Original Title";
  ...
}

Esto funciona porque el comportamiento predeterminado de UINavigationControllercuando se construye el botón de retroceso durante una operación de inserción es usar el título del controlador anterior.


1
El problema con esto es que el título cambia en la vista anterior, ya que se anima y se ve un poco molesto. Ninguna de las soluciones dadas aquí parece funcionar como le gustaría :-(
Danny Tuppeny

1
Esto es perfecto en mi situación porque no muestro la barra de navegación en la pantalla anterior y solo quiero eliminar el título Etiqueta del botón Atrás en la nueva pantalla y solo tengo la flecha de chevron iOS7. Por lo tanto, solo puedo establecer un literal NSString vacío para el título.
siburb

Al presionar el controlador de vista, se genera la excepción cuando se toca la parte posterior
Sumit

7

El título del botón de retroceso predeterminado es el título de la vista anterior, por lo que un truco rápido que uso es colocar el siguiente código en el archivo .m de la vista anterior.

-(void)viewWillAppear:(BOOL)animated {

    // Set title
    self.navigationItem.title=@"Original Title";
}

-(void)viewWillDisappear:(BOOL)animated {

    // Set title
    self.navigationItem.title=@"Back";
}

Esto funciona bastante bien para muchos casos y es bastante simple ... la única observación es que anular cualquiera de estos métodos requiere que la implementación del súper se llame en algún momento del nuevo método.
izk

2
Con este método, se notará que el título de la vista principal se cambia a 'Atrás' antes de que ocurra la animación push. (Y, de alguna manera, apesta, que si mueve esto al método viewDidDisappear, verá que el cambio ocurre después del empuje ...)
James Boutcher

Me encanta este método, pero el problema al que me enfrento es que el "Título original" se establece correctamente, pero viene con puntos suspensivos si es más largo que "Atrás", lo que debe ser porque la vista aún no está en la jerarquía de vistas. , no retransmite la vista de título. El problema descrito por @JamesBoutcher anteriormente es imperceptible para mí debido a la rápida velocidad inicial de la animación. De hecho, me acabo de dar cuenta de que el problema que enfrento es especialmente notable debido a la animación de finalización lenta que es cuando este problema es importante.
trss

Si bien la respuesta en stackoverflow.com/questions/1441699/... parece más personalización de la necesaria, es la forma documentada y, lo que es más importante, parece estar más alineada con nuestra intención.
trss

6

en su método init, agregue el siguiente código:

- (id)initWithStyle:(UITableViewStyle)style {
    if(self = [super init]) {

        //...

        UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" 
                                             style:UIBarButtonItemStylePlain 
                                            target:self 
                                            action:@selector(goBack)];
        self.navigationItem.leftBarButtonItem = customBackButton;
        [customBackButton release];

        //...
    }
    return self;
}

luego agregue un método simple, para permitir el descarte de viewcontroller:

-(void)goBack {
    [self.navigationController popViewControllerAnimated:YES];  
}

3

Agregue el siguiente código en viewDidLoad o loadView

self.navigationController.navigationBar.topItem.title = @"Custom text";

Lo probé en iPhone y iPad con iOS 9


Debe ser self.navigationController? .NavigationBar.backItem? .Title = "Texto personalizado"
Peacemoon

1
La única diferencia que necesitaba era el encadenamiento opcional en las propiedades navigationControllery topItem, por ejemplo:self.navigationController?.navigationBar.topItem?.title = "Custom Text"
Bulwinkel

2

Agregando a la respuesta de Rein. Tenga en cuenta de los documentos de Apple que la declaración de backBarButtonItem es esta:

@property(nonatomic, retain) UIBarButtonItem *backBarButtonItem

Por lo tanto, la respuesta de Rein perderá memoria porque el setter sintetizado será retainla instancia que le pase, que nunca se lanza explícitamente. Puede remediar esto usandoautorelease

 self.navigationItem.backBarButtonItem = 
      [[[UIBarButtonItem alloc] initWithTitle:@"Custom Title" 
         style:UIBarButtonItemStyleBordered
         target:nil
         action:nil] autorelease];  //<-- autoreleased

O podría apuntar una variable a la instancia para que pueda liberarla explícitamente más tarde:

UIBarButtonItem* item = ...
self.navigationItem.backBarButtonItem = item;
[item release];

¡Espero que esto ayude!


Tenga en cuenta que en estos días, con ARC, no necesita preocuparse por la liberación automática (y, de hecho, el compilador producirá un error si intenta liberarla automáticamente en un proyecto habilitado para ARC)
Eric Goldberg

2
- (void)viewDidLoad {
  [super viewDidLoad];

  UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
  self.navigationItem.backBarButtonItem = backButton;
  [backButton release];
}

2

He descubierto algo interesante Si subclasifica UINavigationControllery anula el pushViewController:animated:método y hace algo como esto: (tenga en cuenta que estoy usando ARC)

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] 
 initWithTitle: @"Back" 
 style: UIBarButtonItemStyleBordered
 target: nil action: nil];

viewController.navigationItem.backBarButtonItem = backButton;

[super pushViewController:viewController animated:animated];

Luego, para todos los ViewControllersque se presionan con su controlador de navegación, tendrá el botón "Atrás" automáticamente. Si desea cambiar el texto de ciertos controladores de vista, puede intentar y tal vez convertir el controlador de vista a una determinada clase o su propio protocolo personalizado (que su controlador de vista hereda del cual podría tener un método backButtonTexto algo tonto como ese) que puede darle cierta información sobre el controlador de vista que viene para que pueda personalizar el texto del botón de retroceso. Ahora el texto del botón de retroceso se ocupa en un lugar que debe ser el único responsable. Tengo que admitir que crear un nuevo botón para cambiar el texto apesta, pero bueno.

¿Alguien puede pensar en una razón por la que no hacerlo así? Al menos, no tiene que jugar con los títulos del controlador de vista ni recordar crear un nuevo botón de retroceso antes de presionar el controlador de vista en el controlador de navegación.


0

La respuesta de Rein funciona bien.

Tenga en cuenta que si presiona más de un controlador de vista, aparecerá el título del botón de retroceso modificado para cada uno de ellos, que puede no ser lo que desea.

En ese caso, deberá crear el UIBarButtonItem personalizado cada vez que presione un controlador de vista.

Además, asegúrese de hacerlo antes de presionar el controlador de vista, de lo contrario obtendrá un problema en la pantalla a medida que cambie el título.


0

Ampliando la sugerencia de Aubrey, puede hacer esto en el controlador de vista secundario:

cree dos variables para almacenar los valores antiguos del elemento de navegación principal del objeto y el elemento de navegación del elemento principal

UINavigationItem* oldItem;
NSString* oldTitle;

en viewDidLoad, agregue lo siguiente:

oldItem = self.navigationController.navigationBar.topItem;  
oldTitle = oldItem.title;  
[oldItem setTitle: @"Back"];  

en viewWillDisappear, agregue lo siguiente:

[oldItem setTitle: oldTitle];  
oldTitle = nil;  // do this if you have retained oldTitle
oldItem = nil;   // do this if you have retained oldItem

No es perfecto Verá que el título de la vista principal cambia a medida que se anima el nuevo controlador. PERO esto logra el objetivo de etiquetar de forma personalizada el botón Atrás y mantenerlo en forma de un botón Atrás estándar.


0

Pon esto en ti viewDidLoad, espero que resulte en lo que estás buscando

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Close" 
style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.backBarButtonItem = backBarButtonItem;
[backBarButtonItem release];

0

si desea establecer el título en el controlador LLEGADA (a veces más lógica ...) en swift 3 do:

func setBackButtonNavBar(title: String, delay: Double){

    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: { () -> Void in

        if let navBar = self.navigationController?.navigationBar{
            navBar.backItem?.title = title
        }
    })

}

en el próximo controlador:

override func viewDidLoad() {
    super.viewDidLoad()
    self.setBackButtonNavBar(title: "back", delay: 0.3)
}

generalmente pongo self.setBackButtonNavBar en una extensión de controlador.


0

Sé que esta es una vieja pregunta y las respuestas están un poco actualizadas.

La manera fácil es hacer esto en ViewController primario:

es decir, el que te lleva al siguiente controlador de vista.

self.navigationItem.backBarButtonItem  = UIBarButtonItem(title: "Custom text here", style: .plain, target: nil, action: nil)

-1

Al hacer esto en código, elimine el estilo del botón de retroceso del UINavigationConroller. Si agrega un elemento de navegación en cada una de sus vistas, puede establecer el título del botón de retroceso en StoryBoard.

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.