UINavigationController texte personnalisé «bouton retour»?

147

Le "bouton retour" d'un UINavigationControlleraffiche par défaut le titre de la dernière vue de la pile. Existe-t-il un moyen d'avoir un texte personnalisé dans le bouton de retour à la place?

Ali Shafai
la source
1
Ce travail pour moiself.navigationController.navigationBar.topItem.title = @"Custom text";
huync

Réponses:

342

Depuis ce lien :

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

Comme Tyler l'a dit dans les commentaires:

ne faites pas cela dans le contrôleur de vue visible, mais dans le contrôleur de vue que vous verriez si vous appuyez sur le bouton de retour

rêne
la source
4
Vous devriez releasele UIBarButtonItem.
Mehrdad Afshari
217
Notez également que vous devez le faire dans le contrôleur de vue un niveau plus haut dans la pile. En d'autres termes, ne faites pas cela dans le contrôleur de vue visible, mais dans le contrôleur de vue que vous verriez si vous appuyez sur le bouton de retour.
Tyler le
6
Juste pour clarifier le commentaire de Tyler car je n'ai pas compris cela au début: Définir le backBarButtonItem dans un contrôleur de vue navigationItem définit le bouton qui s'affiche pour revenir à ce contrôleur de vue. Notez également que bien qu'il n'y ait pas de style de bouton pour le bouton fléché, ce bouton obtiendra quand même le style de flèche. J'ai utilisé UIBarButtonItemStylePlain et j'ai toujours le style de bouton fléché.
Jon Steinmetz le
3
Suggestion: plutôt que d'assumer le style, transmettez le style actuellement défini. Dans le code de cette réponse, remplacez UIBarButtonItemStyleBorderedpar un appel à la propriété self.navigationItem.backBarButtonItem.style. Documentation: developer.apple.com/library/ios/documentation/uikit/reference/…
Basil Bourque
1
Notez que sous ARC, vous devez omettre l'appel de libération automatique. vous avez donc self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @ "Titre personnalisé" style: UIBarButtonItemStyleBordered target: nil action: nil];
bkbeachlabs
43

Vous pouvez définir le texte dans Interface Builder:

Sélectionnez l'élément de navigation du ViewController auquel le bouton de retour reviendrait:

entrez la description de l'image ici

Dans l'inspecteur d'attributs du panneau des utilitaires, entrez votre libellé pour le bouton Retour:

entrez la description de l'image ici

Je préférerais cette approche à la définition du titre dans le code comme dans la réponse acceptée.

Notez également que vous devez le faire dans le contrôleur de vue un niveau plus haut dans la pile. En d'autres termes, ne faites pas cela dans le contrôleur de vue visible, mais dans le contrôleur de vue que vous verriez si vous appuyez sur le bouton de retour.
--Tyler

Petr Peller
la source
C'est la meilleure réponse que j'ai trouvée jusqu'à présent.
Ayan Sengupta
2
Pour être clair, cela doit être défini sur l'élément de navigation du contrôleur de vue, et non sur l'inspecteur d'attributs du contrôleur de vue lui-même.
Patrick Lire le
C'est la meilleure réponse que j'ai trouvée.
bicepjai
C'est la meilleure réponse
Alex Brown
2
À partir de Xcode 6.1.1 et fonctionnant sous iOS 7, il semble que votre titre de vue précédent d'origine remplacera TOUJOURS le titre du bouton de retour que vous avez défini ici. Si le titre de la vue précédente contient plus que la limite de 11 caractères, alors le bouton de retour de la vue suivante indiquera simplement «Retour». Il n'y a aucun moyen de contourner cela, sauf pour créer un nouvel élément de barre de navigation à partir de zéro, comme indiqué dans la réponse la plus votée ici.
ray
22

J'utilise ceci:

// 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";
}
Trang
la source
Cela fonctionne presque pour moi, mais lorsque je clique sur le bouton de retour, le texte revient au titre du parent pour la durée de l'animation :-(
Danny Tuppeny
3
Cela modifie le titre du bouton Retour du contrôleur dans la pile. Cela ne change pas le titre du bouton Retour du contrôleur actuellement affiché. Pire encore: cela change le titre du contrôleur antérieur au contrôleur précédent!
leviathan
Comme l'ont noté d'autres commentateurs, cette méthode est un peu intenable. Je ne recommanderais pas de le faire car ce n'est pas vraiment la façon dont l'API vous propose de l'utiliser. Vous pourriez vous préparer à des bugs difficiles à l'avenir!
RickDT
11

J'ai trouvé une solution pratique à cela en définissant simplement le titre du contrôleur avant de pousser un autre contrôleur sur la pile, comme ceci:

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

Ensuite, assurez-vous de définir le titre d'origine viewWillAppear, comme ceci:

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

Cela fonctionne car le comportement par défaut UINavigationControllerlors de la construction du bouton de retour lors d'une opération push est d'utiliser le titre du contrôleur précédent.

Aubrey Goodman
la source
1
Le problème avec cela est que le titre change sur l'ancienne vue car il s'anime et semble un peu nul. Aucune des solutions données ici ne semble fonctionner comme vous le souhaitez :-(
Danny Tuppeny
1
C'est parfait dans ma situation car je n'affiche pas la NavBar sur l'écran précédent et je veux simplement supprimer le titleLabel du bouton de retour sur le nouvel écran et avoir juste la flèche en chevron iOS7. Je peux donc simplement définir un littéral NSString vide pour le titre.
siburb
pousser le contrôleur de vue soulève l'exception lorsque vous appuyez sur le dos
Sumit
7

Le titre du bouton de retour est par défaut le titre de la vue précédente, donc une astuce rapide que j'utilise consiste à placer le code suivant sur le fichier .m de la vue précédente.

-(void)viewWillAppear:(BOOL)animated {

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

-(void)viewWillDisappear:(BOOL)animated {

    // Set title
    self.navigationItem.title=@"Back";
}
AddisDev
la source
Cela fonctionne plutôt bien dans de nombreux cas et c'est assez simple ... la seule observation est que la substitution de l'une ou l'autre de ces méthodes nécessite que l'implémentation du super soit appelée à un moment donné dans la nouvelle méthode.
izk
2
Avec cette méthode, on remarquera que le titre de la vue parent est changé en «Retour» avant que l'animation push ne se produise. (Et, en quelque sorte, ça craint, que si vous déplacez cela vers la méthode viewDidDisappear, vous verrez le changement se produire après le push ..)
James Boutcher
J'adore cette méthode, mais le problème auquel je suis confronté est que le "Titre d'origine" est réglé correctement, mais il est livré avec des points de suspension s'il est plus long que "Back", ce qui doit être parce que, puisque la vue n'est pas encore dans la hiérarchie des vues , il ne retransmet pas la vue titre. Le problème décrit par @JamesBoutcher ci-dessus est imperceptible pour moi en raison de la vitesse initiale rapide de l'animation. En fait, je viens de réaliser que le problème auquel je suis confronté est particulièrement perceptible en raison de la lenteur de l'animation qui se termine lorsque ce problème est important.
trss le
Alors que la réponse à stackoverflow.com/questions/1441699/ ... semble plus de personnalisation que nécessaire, c'est la manière documentée et, plus important encore, semble être plus alignée sur notre intention.
trss le
6

dans votre méthode init, ajoutez le code suivant:

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

puis ajoutez une méthode simple, pour permettre le rejet de viewcontroller:

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

Ajoutez le code suivant dans viewDidLoad ou loadView

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

Je l'ai testé sur iPhone et iPad avec iOS 9

seul
la source
Devrait être self.navigationController? .NavigationBar.backItem? .Title = "Texte personnalisé"
Peacemoon
1
la seule différence dont j'avais besoin était le chaînage facultatif sur les propriétés navigationControlleret topItem, par exemple:self.navigationController?.navigationBar.topItem?.title = "Custom Text"
Bulwinkel
2

Ajout à la réponse de rein. Notez dans la documentation d'Apple que la déclaration de backBarButtonItem est la suivante:

@property(nonatomic, retain) UIBarButtonItem *backBarButtonItem

Par conséquent, la réponse de rein fuira de la mémoire car le setter synthétisé sera retainl'instance que vous lui transmettez, qui n'est jamais libérée explicitement. Vous pouvez remédier à cela en utilisantautorelease

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

Ou vous pouvez pointer une variable sur l'instance afin de pouvoir la libérer explicitement plus tard:

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

J'espère que cela t'aides!

Eric Goldberg
la source
Notez que ces jours-ci, avec ARC, vous n'avez pas à vous soucier de la libération automatique (et en effet le compilateur fera une erreur si vous essayez de publier automatiquement dans un projet compatible 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];
}
LCANT
la source
2

J'ai découvert quelque chose d'intéressant. Si vous sous-classez leUINavigationController classez et remplacez la pushViewController:animated:méthode et faites quelque chose comme ceci: (gardez à l'esprit que j'utilise ARC)

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

viewController.navigationItem.backBarButtonItem = backButton;

[super pushViewController:viewController animated:animated];

Ensuite, pour tout ce ViewControllersqui est poussé avec votre contrôleur de navigation aura le bouton "Retour" en eux automatiquement. Si vous voulez changer le texte de certains contrôleurs de vue, vous pouvez essayer de convertir le contrôleur de vue dans une certaine classe ou votre propre protocole personnalisé (dont votre contrôleur de vue hérite et qui pourrait avoir une méthode comme backButtonTextou quelque chose de stupide comme ça) qui peut vous donner certaines informations sur le viewcontroller qui arrive afin que vous puissiez personnaliser le texte du bouton de retour pour cela. Désormais, le texte du bouton de retour est pris en charge dans un endroit qui ne devrait en être que responsable. Je dois admettre que créer un nouveau bouton pour changer le texte est nul, mais bon.

Quelqu'un peut-il penser à une raison pour laquelle ne pas le faire comme ça? Au moins, vous n'avez pas à jouer avec les titres du contrôleur de vue ou à vous rappeler de créer un nouveau bouton de retour avant d'appuyer sur le contrôleur de vue sur le contrôleur de navigation.

Dandré
la source
0

La réponse de rein fonctionne bien.

Notez que si vous appuyez sur plusieurs contrôleurs de vue, le titre du bouton de retour modifié apparaîtra pour chacun d'eux, ce qui peut ne pas être ce que vous souhaitez.

Dans ce cas, vous devrez créer le UIBarButtonItem personnalisé chaque fois que vous poussez un contrôleur de vue.

Assurez-vous également de le faire avant d' appuyer sur le contrôleur de vue, sinon vous obtiendrez un hoquet d'écran lorsque le titre changera.

homme du Nord
la source
0

En développant la suggestion d'Aubrey, vous pouvez le faire dans le contrôleur de vue enfant:

créer deux variables pour stocker les anciennes valeurs de navigationItem.title du parent et navigationItem du parent

UINavigationItem* oldItem;
NSString* oldTitle;

dans viewDidLoad, ajoutez ce qui suit:

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

dans viewWillDisappear, ajoutez ce qui suit:

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

Ce n'est pas parfait. Vous verrez le titre de la vue parent changer au fur et à mesure que le nouveau contrôleur est animé. MAIS cela permet d'atteindre l'objectif d'étiqueter personnalisé le bouton de retour et de le garder en forme de bouton de retour standard.

FingerTipFun
la source
0

Mettez cela en vous viewDidLoad, espérons que cela aboutira à ce que vous recherchez

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

si vous souhaitez définir le titre dans le contrôleur ARRIVING (parfois plus de logique ..) dans swift 3, faites:

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
        }
    })

}

dans le prochain contrôleur:

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

généralement, je mets self.setBackButtonNavBar dans une extension de contrôleur.

ingconti
la source
0

Je sais que c'est une vieille question et les réponses sont en quelque sorte mises à jour!

Le moyen le plus simple est de le faire dans le ViewController parent:

c'est-à-dire celui qui vous amène au contrôleur de vue suivant.

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

Cette opération dans le code supprime le style de bouton de retour du UINavigationConroller. Si vous ajoutez un élément de navigation dans chacune de vos vues, vous pouvez définir le titre du bouton arrière dans le StoryBoard.

gjseminario
la source