2010-08-17 11 views
17

Pour une application que je développe, j'ai besoin d'afficher un bouton de retour personnalisé dans une barre de navigation. Je l'actif bouton comme une image PNG, et je vous écris ce code:Bouton de retour personnalisé dans UINavigationController

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
    backButton.frame = CGRectMake(0, 0, 79, 29.0); 
    [backButton setImage:[UIImage imageNamed:@"button_back.png"] forState:UIControlStateNormal]; 
    self.navigationItem.backBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease]; 

}

Quand je pousse ce contrôleur de vue, le bouton personnalisé ne se présente pas, et au lieu que je reçois la bouton de retour standard avec le titre de ce contrôleur de vue à l'intérieur.

choses que j'ai déjà essayé:

  1. chèque Doublement que le bouton backButton est créé correctement, en l'ajoutant à la hiérarchie de la vue. Il affiche correctement.
  2. Dans la même méthode, a modifié la propriété title du navigationItem et a confirmé qu'il modifie (comme prévu) le contenu de mon bouton Précédent.

Quelqu'un peut-il repérer ce que je fais mal? Est-ce que quelqu'un a réussi à utiliser une image personnalisée comme bouton de retour avec un UINavigationController?

Répondre

5

La propriété backBarButtonItem fonctionne comme prévu, mais sa couleur et sa forme standard seront toujours ajoutées en fonction de la couleur de la barre de navigation.

Vous pouvez personnaliser le texte, mais pas remplacer l'image. Une solution de contournement, comme Andrew Pouliot l'a suggéré, consiste à utiliser leftBarButtonItem à la place, mais je me suis contenté du bouton standard à la place.

3

Confusément backBarButtonItem n'est pas ce que vous cherchez.

Il contrôle simplement le titre sur le bouton de retour pour le contrôleur de vue suivant. Ce que vous voulez est de mettre le leftBarButtonItem à votre bouton de retour personnalisé.

+3

Je pense que je veux 'backBarButtonItem'. Ce que je veux contrôler, c'est à quoi ressemblera le bouton arrière quand le 'UIViewController' sera poussé dans la pile' UINavigationController'. En effet, des modifications mineures du 'backBarButtonItem' fonctionnent comme prévu, c'est juste la vue personnalisée qui ne colle pas. – pgb

+1

La propriété backBarButtonItem fonctionne. Il suffit de le mettre au bon moment. – SundayMonday

0

créer simplement un UIBarButtonItem au lieu d'un noyé UIButton dans UIBarButtonItem. Fonctionne bien!

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"button_back.png"] style:UIBarButtonItemStyleBordered target:nil action:nil]; 

self.navigationItem.backBarButtonItem = backButton; 
+1

Cela ne fonctionne pas. L'image d'arrière-plan du bouton arrière est toujours affichée (sauf si l'image que vous utilisez est plus grande que l'image du bouton arrière par défaut) – probablyCorey

+0

http: // stackoverflow.com/questions/526520/how-to-create-backbarbuttomitem-avec-custom-view-for-a-uinavigationcontroller/7184426 # 7184426 – SundayMonday

18

A partir de iOS 5, est simple:

[[UIBarButtonItem appearance] 
      setBackButtonBackgroundImage:[UIImage imageNamed:@"back_button.png"] 
      forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; 

Vous pouvez placer que votre délégué de l'application et il sera définir l'image d'arrière-plan à tous les boutons de retour dans l'application (pour cet état de contrôle et les mesures de bar , bien sûr).

+27

Cela ne cache pas le titre de backbutton – user366584

+5

Une façon de masquer le titre de backbutton ?? – ArdenDev

+1

De cette façon, la largeur de l'arrière-plan dépend de la longueur du titre. L'image sera étirée en fonction de la longueur du titre. – Add080bbA

13

Je reposter ma solution de https://stackoverflow.com/a/16831482/171933:

Je crée une catégorie simple sur UIViewController:

UIViewController + ImageBackButton.h

#import <UIKit/UIKit.h> 

@interface UIViewController (ImageBackButton) 

- (void)setUpImageBackButton; 

@end 

UIViewController + ImageBackButton.m

#import "UIViewController+ImageBackButton.h" 

@implementation UIViewController (ImageBackButton) 

- (void)setUpImageBackButton 
{ 
    UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 34, 26)]; 
    [backButton setBackgroundImage:[UIImage imageNamed:@"back_arrow.png"] forState:UIControlStateNormal]; 
    UIBarButtonItem *barBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; 
    [backButton addTarget:self action:@selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside]; 
    self.navigationItem.leftBarButtonItem = barBackButtonItem; 
    self.navigationItem.hidesBackButton = YES; 
} 

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

@end 

Maintenant, tout ce que vous avez à faire est #import UIViewController+ImageBackButton.h soit dans tous vos vue contrôleurs ou dans une classe de contrôleur de vue de base sur mesure que vos autres contrôleurs de vue hériteront de et mettre en œuvre la méthode viewWillAppear::

- (void)viewWillAppear:(BOOL)animated 
{ 
    [self setUpImageBackButton]; 
} 

C'est tout. Maintenant vous avez un bouton de retour d'image partout. Sans frontière. Prendre plaisir!

+0

[backButton addTarget: action self.navigationController: @selector (popViewControllerAnimated :) forControlEvents: UIControlEventTouchUpInside]; ne fournit pas l'argument 'animé' et n'est pas défini. il vaut mieux juste ajouter une méthode qui fournit explicitement l'argument 'animé' –

+0

@OrArbel Merci, vous avez raison. Cela fonctionne comme il est, mais il est plus propre de l'appeler explicitement. J'ai modifié le code :) –

+1

Ceci est correct mais désactivera le balayage pour revenir en arrière si vous masquez le bouton de retour. Donc, vous perdez plus que vous gagnez. – AppHandwerker

3

La solution la plus simple n'est-elle pas de la concevoir à partir de votre storyboard avec l'image ou les couleurs que vous voulez, et de faire glisser une nouvelle action sur votre contrôleur?

Swift Code

@IBAction func backButton(sender: AnyObject) { 
    self.navigationController?.popViewControllerAnimated(true) 
} 
+3

SO est tellement génial! J'ai posé cette question en 2010, et j'obtiens une réponse maintenant avec un exemple de code Swift, et en suggérant l'utilisation de Storyboards :) – pgb

1

Je ne pense pas que ViewController lui-même doit savoir quelque chose sur le bouton retour Selon POO c'est la responsabilité de containerViewController dans lequel votre contrôleur de vue est inséré , par exemple UINavigationController.

Sous votre NavigationController et surcharge dans ce superClass méthode comme ceci:

@implementation STONavigationController 

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    [super pushViewController:viewController animated:animated]; 
    if ([self.viewControllers indexOfObject:viewController] != NSNotFound && 
     [self.viewControllers indexOfObject:viewController] > 0){ 
     UIImage *img = [UIImage imageNamed:@"back-1"]; 
     UIButton *backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, img.size.width * 2, img.size.height * 2)]; 
     [backButton setBackgroundImage:img forState:UIControlStateNormal]; 
     UIBarButtonItem *barBackButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton]; 
     [backButton addTarget:self action:@selector(popCurrentViewController) forControlEvents:UIControlEventTouchUpInside]; 
     viewController.navigationItem.leftBarButtonItem = barBackButtonItem; 
     viewController.navigationItem.hidesBackButton = YES; 
    } 
} 

- (void)popCurrentViewController 
{ 
    [self popViewControllerAnimated:YES]; 
} 

@end 
1

Johannes Fahrenkrug œuvres de réponse, mais l'image arrière apparaîtraient à une position très câblé.

Ici, je trouve une meilleure façon de positionner l'image au bon endroit:

Assurez-vous que vous avez une image en arrière avec la taille 24x24 (@ 1x), je l'appelle backImage

Exécutez le code suivant lorsque votre application Lancement

UINavigationBar.appearance().barTintColor = nil 
UINavigationBar.appearance().backIndicatorImage = backImage 
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage 
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics: .Default) 
+0

J'ai réglé setBackButtonTitlePositionAdjustment sur didFinishLaunchingWithOptions et dans certains écrans je peux voir le titre du bouton de retour s'animer hors écran: / –

0

Comme suggéré @pgb vous pouvez utiliser leftBarButtonItem au lieu de l'élément de bouton retour. Et pour supprimer l'élément de bouton de retour par défaut, réglez-le à zéro comme suit;

navigationController?.navigationBar.backIndicatorImage = nil 
navigationController?.navigationBar.backIndicatorTransitionMaskImage = nil 

let button = UIButton.init(type: .custom) 
button.imageView?.contentMode = UIViewContentMode.scaleAspectFit 
button.setImage(UIImage.init(named: "top_back"), for: UIControlState.normal) 
button.frame = CGRect.init(x: 0, y: 0, width: 75, height: 50) 
button.addTarget(self, action: #selector(handleBackButton), for: .touchUpInside) 

let barButton = UIBarButtonItem.init(customView: button) 
self.navigationItem.leftBarButtonItem = barButton 
Questions connexes