Pour une application que je développe, je dois afficher un bouton Précédent personnalisé dans une barre de navigation. J'ai l'actif du bouton sous forme d'image PNG et j'écris ce code:
- (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];
}
Lorsque j'appuie sur ce contrôleur de vue, le bouton personnalisé n'apparaît pas et je reçois à la place le bouton retour standard avec le titre de ce contrôleur de vue à l'intérieur.
Choses que j'ai déjà essayées:
backButton
est créé correctement en l’ajoutant à la hiérarchie des vues. Il affiche correctement.title
de la navigationItem
et confirmez qu'elle modifie (comme prévu) le contenu de mon bouton de retour.Quelqu'un peut-il repérer ce que je fais mal? Quelqu'un at-il réussi à utiliser une image personnalisée comme bouton de retour avec une variable UINavigationController
?
La propriété backBarButtonItem
fonctionne comme prévu, mais elle ajoutera toujours sa forme et sa couleur de bouton standard en fonction de la couleur de la teinte de la barre de navigation.
Vous pouvez personnaliser le texte, mais pas remplacer l'image.
Une solution de rechange, comme l'a suggéré Andrew Pouliot, consiste à utiliser leftBarButtonItem
à la place, mais je suis resté bloqué sur le bouton standard.
À partir de iOS 5, c'est simple:
[[UIBarButtonItem appearance]
setBackButtonBackgroundImage:[UIImage imageNamed:@"back_button.png"]
forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
Vous pouvez l'insérer dans le délégué de votre application pour définir l'image d'arrière-plan sur tous les boutons de retour de l'application (pour cet état de contrôle et cette mesure de barre, bien sûr).
Je republie 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
Tout ce que vous avez à faire est maintenant #import UIViewController+ImageBackButton.h
dans tous vos contrôleurs de vue ou dans une classe de contrôleur de vue de base personnalisée dont vos autres contrôleurs de vue héritent et implémentent la méthode viewWillAppear:
:
- (void)viewWillAppear:(BOOL)animated
{
[self setUpImageBackButton];
}
C'est tout. Maintenant, vous avez un bouton de retour d'image partout. Sans bordure. Prendre plaisir!
La solution la plus simple n’est-elle pas simplement de la concevoir à partir de votre scénario avec l’image ou les couleurs de votre choix et de faire simplement glisser une nouvelle action sur votre contrôleur?
Code rapide
@IBAction func backButton(sender: AnyObject) { self.navigationController?.popViewControllerAnimated(true) }
Confusément, backBarButtonItem
n'est pas ce que vous recherchez.
Il contrôle simplement le titre sur le bouton Précédent pour le prochain contrôleur de vue. Ce que vous voulez, c'est définir le leftBarButtonItem
sur votre bouton retour personnalisé.
Voir cette réponse ici: Comment créer backBarButtomItem avec une vue personnalisée pour un UINavigationController
Il vous suffit de définir la propriété backBarButtonItem
sur le navigationController before en poussant le viewController. La définition de la propriété backBarButtonItem
dans la méthode viewDidLoad
du viewController (par exemple) ne fonctionne pas.
La réponse de Johannes Fahrenkrug fonctionne, mais l'image arrière apparaîtrait à une position très câblée.
Ici, j'ai trouvé un meilleur moyen de positionner l'image au bon endroit:
Assurez-vous d'avoir une image au format 24x24 (@ 1x), je l'appelle backImage
Exécutez le code suivant au lancement de votre application.
UINavigationBar.appearance().barTintColor = nil
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics: .Default)
Je ne pense pas que ViewController lui-même ne devrait rien savoir de son bouton Précédent Selon OOP, cette responsabilité incombe à containerViewController dans lequel votre contrôleur de vue est inséré, par exemple UINavigationController.
Sous-classez votre NavigationController et surchargez-y la méthode superClass 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
Comme @pgb l'a suggéré, vous pouvez utiliser leftBarButtonItem au lieu d'un élément du bouton Précédent. Et pour supprimer l’élément de bouton Précédent par défaut, définissez-le sur nil 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
Créez simplement une UIBarButtonItem
au lieu d'une UIButton
incorporée dans UIBarButtonItem
. Fonctionne bien!
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"button_back.png"] style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;