Création d'un bouton avec une flèche vers la gauche (comme le style «arrière» de UINavigationBar) sur une barre UIToolbar

StackOverflow https://stackoverflow.com/questions/227078

Question

J'aimerais créer un " retour " bouton flèche gauche dans un UIToolbar .

Autant que je sache, le seul moyen d’en obtenir un est de laisser UINavigationController dans les paramètres par défaut et il en utilise un pour l’élément de barre de gauche. Mais je ne peux absolument pas en créer un en tant que UIBarButtonItem . Je ne peux donc pas en créer un dans un UIToolbar standard, même s'ils sont très similaires à UINavigationBar s.

Je pouvais le créer manuellement avec des images de boutons, mais je ne peux trouver les images sources nulle part. Ils ont des bords de canal alpha, de sorte que les captures d'écran et les découpes n'obtiendront pas des résultats très polyvalents.

Avez-vous des idées autres que la capture d'écran pour chaque taille et palette de couleurs que je compte utiliser?

Mise à jour : VEUILLEZ CESSER d'esquiver la question et de suggérer que je ne devrais plus poser cette question ni utiliser UINavigationBar . Mon application est Instapaper Pro. Elle affiche uniquement une barre d’outils inférieure (pour économiser de l’espace et maximiser la zone de contenu lisible), et je souhaite placer un bouton Précédent en forme de flèche vers la gauche dans le bas.

Me dire que je ne devrais pas avoir à faire cela n'est pas une réponse et ne mérite certainement pas une prime.

Était-ce utile?

La solution

J'ai utilisé le psd suivant dérivé de http://www.teehanlax.com / blog /? p = 447

http://www.chrisandtennille.com/pictures/backbutton.psd

Je viens alors de créer un UIView personnalisé que j'utilise dans la propriété customView de l'élément de la barre d'outils.

Fonctionne bien pour moi.

Modifier: Comme le soulignait PrairieHippo , maralbjo a constaté que l'utilisation du code simple suivant fonctionnait (nécessite une image personnalisée dans le lot ) devrait être combiné avec cette réponse. Donc, voici le code supplémentaire:

// Creates a back button instead of default behaviour (displaying title of previous screen)
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_arrow.png"]
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(backAction)];

tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
[backButton release];

Autres conseils

La méthode Unicode

Je pense qu'il est beaucoup plus facile de simplement utiliser un caractère Unicode pour faire le travail. Vous pouvez regarder à travers les flèches en cherchant Google, Triangles Unicode ou < a href = "http://www.fileformat.info/info/unicode/block/arrows/list.htm" rel = "nofollow noreferrer"> Flèches Unicode . À partir de iOS6, Apple a changé le caractère en un personnage emoji avec une bordure. Pour désactiver la bordure, j’ajoute le sélecteur de variation Unicode , 0xFE0E.

NSString *backArrowString = @"\U000025C0\U0000FE0E"; //BLACK LEFT-POINTING TRIANGLE PLUS VARIATION SELECTOR

UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:backArrowString style:UIBarButtonItemStylePlain target:nil action:nil];
self.navigationItem.leftButtonItem = backBarButtonItem;

Le bloc de code est juste pour la démo. Cela fonctionnerait avec n’importe quel bouton acceptant une chaîne NSString.

Pour obtenir une liste complète des caractères, recherchez dans Google un caractère Unicode et ce que vous voulez. Voici l'entrée du Triangle noir pointant à gauche .

Résultat

Le résultat

AVERTISSEMENT: certains rapports signalent que cela ne fonctionnera pas sous iOS 6. Cela ne fonctionne peut-être que sur les anciennes versions du système d'exploitation. De toute évidence, au moins un développeur a vu son application rejetée pour utiliser cette astuce (voir les commentaires). À utiliser à vos risques et périls. Utiliser une image (voir la réponse ci-dessus) pourrait constituer une solution plus sûre.

Cela peut être fait sans ajouter vos propres fichiers image en utilisant le type de bouton 101 de sekr1t pour obtenir la forme correcte. Pour moi, le truc était de comprendre que je pouvais utiliser initWithCustomView pour créer le BarButtonItem . Personnellement, j’en avais besoin pour une barre de navigation dynamique plutôt que pour une barre d’outils , mais je l’ai testée avec une barre d’outils et le code est presque identique:

// create button
UIButton* backButton = [UIButton buttonWithType:101]; // left-pointing shape!
[backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"Back" forState:UIControlStateNormal];

// create button item -- possible because UIButton subclasses UIView!
UIBarButtonItem* backItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];

// add to toolbar, or to a navbar (you should only have one of these!)
[toolbar setItems:[NSArray arrayWithObject:backItem]];
navItem.leftBarButtonItem = backItem;

Si vous faites cela dans une barre d’outils, vous devrez modifier la manière dont vous définissez les éléments, mais cela dépend du reste de votre code et je le laisse comme exercice pour le lecteur. : P Cet exemple a fonctionné pour moi (compilé et exécuté).

Blah blah, lisez le HIG, n'utilisez pas de fonctionnalités non documentées, etc. Il n’existe que six types de boutons pris en charge, et ce n’est pas l’un d’entre eux.

entrer la description de l'image ici

Tout d’abord, vous devez trouver une image du bouton de retour. J'ai utilisé une application intéressante appelée Extractor , qui extrait tous les graphiques de l'iPhone. Dans iOS7 , je suis parvenu à récupérer l'image appelée UINavigationBarBackIndicatorDefault et elle était de couleur noire, car j'avais besoin d'une teinte rouge . Je change la couleur en rouge à l'aide de Gimp.

EDIT:

Comme indiqué par btate dans son commentaire, il n'est pas nécessaire de modifier la couleur avec l'éditeur d'image. Le code suivant devrait faire l'affaire:

imageView.tint = [UIColor redColor];
imageView.image = [[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];

Ensuite, j'ai créé une vue contenant une image View avec cette flèche, une étiquette avec le texte personnalisé et au-dessus de la vue, un bouton avec une action. Ensuite, j'ai ajouté une animation simple (fondu et traduction).

Le code suivant simule le comportement du bouton Précédent, y compris l'animation.

-(void)viewWillAppear:(BOOL)animated{
        UIImageView *imageView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"UINavigationBarBackIndicatorDefault"]];
        [imageView setTintColor:[UIColor redColor]];
        UILabel *label=[[UILabel alloc] init];
        [label setTextColor:[UIColor redColor]];
        [label setText:@"Blog"];
        [label sizeToFit];

        int space=6;
        label.frame=CGRectMake(imageView.frame.origin.x+imageView.frame.size.width+space, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
        UIView *view=[[UIView alloc] initWithFrame:CGRectMake(0, 0, label.frame.size.width+imageView.frame.size.width+space, imageView.frame.size.height)];

        view.bounds=CGRectMake(view.bounds.origin.x+8, view.bounds.origin.y-1, view.bounds.size.width, view.bounds.size.height);
        [view addSubview:imageView];
        [view addSubview:label];

        UIButton *button=[[UIButton alloc] initWithFrame:view.frame];
        [button addTarget:self action:@selector(handleBack:) forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:button];

        [UIView animateWithDuration:0.33 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            label.alpha = 0.0;
            CGRect orig=label.frame;
            label.frame=CGRectMake(label.frame.origin.x+25, label.frame.origin.y, label.frame.size.width, label.frame.size.height);
            label.alpha = 1.0;
            label.frame=orig;
        } completion:nil];

        UIBarButtonItem *backButton =[[UIBarButtonItem alloc] initWithCustomView:view];
}

- (void) handleBack:(id)sender{
}

EDIT:

Au lieu d’ajouter le bouton, à mon avis, la meilleure approche consiste à utiliser un dispositif de reconnaissance des gestes.

UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBack:)];
[view addGestureRecognizer:tap];
[view setUserInteractionEnabled:YES];

Je ne suis pas sûr que cela fonctionne, mais vous pouvez essayer de créer un UINavigationController avec les paramètres par défaut pour créer le bouton, recherchez le bouton dans la hiérarchie de sous-vue du contrôleur de navigation, appelez . removeFromSuperview , détruisez le contrôleur de navigation, puis ajoutez le bouton en tant que sous-vue de votre barre d'outils. Vous devrez peut-être aussi conserver et le bouton avant d'appeler removeFromSuperview (puis relâchez après l'avoir ajouté en tant que sous-vue de votre barre d'outils) pour l'éviter être désalloué au cours du processus.

Pour créer un UIButton avec une flèche très proche (je ne suis pas un concepteur;) du système iOS 7, flèche arrière:

Standard:

Flèche de retour du système standard

Apple SD Gothic Neo

Apple SD Gothique Neo <caractère

Dans Xcode:

  • Concentrez-vous sur le champ de valeur du titre du bouton (ou sur toute autre vue / commande avec du texte)
  • Ouvrir Éditer - > Caractères spéciaux
  • Sélectionnez le groupe de parenthèses et double-cliquez sur le '<' caractère
  • Remplacez la police par: Apple SD Gothic Neo, Normal avec la taille souhaitée (par exemple 20)
  • Changez de couleur à votre guise

Référez-vous à la réponse de @ staticVoidMan à la flèche semblable à Retour sur iOS 7

 flèche retour

Si vous ne souhaitez pas vous soucier des fichiers image, la forme de la flèche peut être dessinée dans une sous-classe UIView avec le code suivant:

- (void)drawRect:(CGRect)rect {
    float width = rect.size.width;
    float height = rect.size.height;
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextBeginPath(context);
    CGContextMoveToPoint(context, width * 5.0/6.0, height * 0.0/10.0);
    CGContextAddLineToPoint(context, width * 0.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 5.0/6.0, height * 10.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 9.0/10.0);
    CGContextAddLineToPoint(context, width * 2.0/6.0, height * 5.0/10.0);
    CGContextAddLineToPoint(context, width * 6.0/6.0, height * 1.0/10.0);
    CGContextClosePath(context);

    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
    CGContextFillPath(context);
}

où la vue en flèche est proportionnelle à une largeur de 6,0 et à une hauteur de 10,0

    self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;

Fonctionne pour moi. J'utilisais cette option lorsque j'avais plus d'onglets que je pouvais insérer dans la barre d'onglets et qu'un contrôleur de vue était poussé à partir de l'option "Plus". substituer le leftBarButtonItem dans son viewDidLoad.

Vous pouvez trouver les images sources en les extrayant de Other.artwork dans UIKit $ {SDKROOT} /System/Library/Frameworks/UIKit.framework/Other.artwork. La communauté de modding a quelques outils pour les extraire, ici . Une fois que vous extrayez l'image, vous pouvez écrire du code pour le recolorer au besoin et le définir comme image de bouton. Que vous puissiez ou non envoyer une telle chose (puisque vous intégrez des œuvres d'art dérivées) est peut-être un peu risqué, alors vous voudrez peut-être parler à un avocat.

La bibliothèque Three20 a le moyen de le faire:

  UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle: @"Title" style:UIBarButtonItemStylePlain 
                                                                target:self action:@selector(foo)];

  UIColor* darkBlue = RGBCOLOR(109, 132, 162);

  TTShapeStyle* style = [TTShapeStyle styleWithShape:[TTRoundedLeftArrowShape shapeWithRadius:4.5] next:
    [TTShadowStyle styleWithColor:RGBCOLOR(255,255,255) blur:1 offset:CGSizeMake(0, 1) next:
    [TTReflectiveFillStyle styleWithColor:darkBlue next:
    [TTBevelBorderStyle styleWithHighlight:[darkBlue shadow]
                                     shadow:[darkBlue multiplyHue:1 saturation:0.5 value:0.5]
                                      width:1 lightSource:270 next:
    [TTInsetStyle styleWithInset:UIEdgeInsetsMake(0, -1, 0, -1) next:
    [TTBevelBorderStyle styleWithHighlight:nil shadow:RGBACOLOR(0,0,0,0.15)
                                        width:1 lightSource:270 next:nil]]]]]];

  TTView* view = [[[TTView alloc] initWithFrame:CGRectMake(0, 0, 80, 35)] autorelease];
  view.backgroundColor = [UIColor clearColor];
  view.style = style;
  backButton.customView = view;


  self.navigationItem.leftBarButtonItem = backButton;

J'ai constaté que l'utilisation du code suivant, très simple, permettait de résoudre le problème (nécessite une image personnalisée dans son ensemble):

// Creates a back button instead of default behaviour (displaying title of previous screen)
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_arrow.png"]
                                                                   style:UIBarButtonItemStyleBordered
                                                                  target:self
                                                                  action:@selector(backAction)];

    tipsDetailViewController.navigationItem.leftBarButtonItem = backButton;
    [backButton release];

Voici ce que j'ai fini par faire après avoir recherché toutes ces solutions et d'autres. Il utilise un fichier png extensible extrait des images de stock UIKit. De cette façon, vous pouvez définir le texte comme bon vous semble

// Generate the background images
UIImage *stretchableBackButton = [[UIImage imageNamed:@"UINavigationBarDefaultBack.png"] stretchableImageWithLeftCapWidth:14 topCapHeight:0];
UIImage *stretchableBackButtonPressed = [[UIImage imageNamed:@"UINavigationBarDefaultBackPressed.png"] stretchableImageWithLeftCapWidth:13 topCapHeight:0];
// Setup the UIButton
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[backButton setBackgroundImage:stretchableBackButton forState:UIControlStateNormal];
[backButton setBackgroundImage:stretchableBackButtonPressed forState:UIControlStateSelected];
NSString *buttonTitle = NSLocalizedString(@"Back", @"Back");
[backButton setTitle:buttonTitle forState:UIControlStateNormal];
[backButton setTitle:buttonTitle forState:UIControlStateSelected];
backButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 2, 1); // Tweak the text position
NSInteger width = ([backButton.titleLabel.text sizeWithFont:backButton.titleLabel.font].width + backButton.titleEdgeInsets.right +backButton.titleEdgeInsets.left);
[backButton setFrame:CGRectMake(0, 0, width, 29)];
backButton.titleLabel.font = [UIFont boldSystemFontOfSize:13.0f];
[backButton addTarget:self action:@selector(yourSelector:) forControlEvents:UIControlEventTouchDown];
// Now add the button as a custom UIBarButtonItem
UIBarButtonItem *backButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:backButton] autorelease];
self.navigationItem.leftBarButtonItem = backButtonItem;

C’est facile à faire avec Interface Builder dans Xcode 5.x

.

Résultat

  • utiliser Barre d'outils et Élément de bouton de barre dans Bibliothèque d'objets

    Composants

  • dans la section de l'inspecteur d'attributs du modificateur de l'image Image avec votre image du bouton de retour

    Inspecteur d'attributs

Fait!

J'essayais de faire la même chose, mais je voulais que le bouton Précédent se trouve dans la barre de navigation. (J'avais en fait besoin d'un bouton de retour, ce qui ferait plus que simplement revenir en arrière, j'ai donc dû utiliser la propriété leftBarButtonItem). J’ai essayé ce qu’AndrewS avait suggéré, mais dans la barre de navigation, cela ne ressemblerait pas à ce qu’il devrait être, car le UIButton a été jeté sur un UIBarButtonItem.

Mais j'ai trouvé un moyen de contourner ce problème. En fait, je viens de mettre UIView sous UIButton et de définir customView pour UIBarButtonItem. Voici le code, si quelqu'un en a besoin:

// initialize button and button view
UIButton *backButton = [UIButton buttonWithType:101];
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, backButton.frame.size.width, backButton.frame.size.height)];

[backButton addTarget:self action:@selector(backButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:@"Back" forState:UIControlStateNormal];
[backButtonView addSubview:backButton];

// set buttonview as custom view for bar button item
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButtonItem;

// push item to navigationbar items
[self.navigationController.navigationBar setItems:[NSArray arrayWithObject:backButtonItem]];

Pour créer une image pour la barre UIToolbar, créez un png dans photoshop et WHERE EVER, quelle que soit sa couleur, il le met en blanc et où il est alpha = 0, il le laisse seul.

Le SDK a placé la bordure autour de l'icône que vous avez créée et la rend blanche sans que vous ayez à faire quoi que ce soit.

Vous voyez, c’est ce que j’ai fait dans Photoshop pour mon bouton suivant (évidemment le permuter pour un bouton précédent):

http://twitpic.com/1oanv

et voici à quoi il ressemblait dans Interface Builder

http://twitpic.com/1oaoa

Solution SANS utiliser un png. Sur la base de cette réponse SO: Ajout de la petite flèche à droite d'une cellule dans une cellule TableView iPhone iPhone

Basculez horizontalement UITableViewCell!

UIButton *btnBack = [[UIButton alloc] initWithFrame:CGRectMake(0, 5, 70, 20)];

// Add the disclosure
CGRect frm;
UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.transform = CGAffineTransformScale(CGAffineTransformIdentity, -1, 1);
frm = self.btnBack.bounds;
disclosure.frame = CGRectMake(frm.origin.x, frm.origin.y, frm.size.width-25, frm.size.height);
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
disclosure.userInteractionEnabled = NO;
[self.btnBack addSubview:disclosure];

// Add the label
UILabel *lbl = [[UILabel alloc] init];
frm = CGRectOffset(self.btnBack.bounds, 15, 0);
lbl.frame = frm;
lbl.textAlignment = NSTextAlignmentCenter;
lbl.text = @"BACK";
[self addSubview:lbl];

Si vous voulez éviter de le dessiner vous-même, vous pouvez utiliser la classe non documentée: Bouton de navigation avec le style 1. Cela peut, bien sûr, empêcher votre demande d'être approuvée ... / John

Eh bien, vous n'avez pas besoin d'un bouton différent pour chaque taille, vous pouvez utiliser [UIImage stretchableImageWithLeftCapWidth: topCapHeight:] , mais la seule chose que j'ai trouvée est des images personnalisées.

J'ai eu un problème similaire et une bibliothèque PButton . Et l'exemple est le bouton de navigation arrière comme le bouton, qui peut être utilisé n'importe où, comme un bouton personnalisé.

Quelque chose comme ça: entrer la description de l'image ici

Exemple dans Swift 3, avec un bouton précédent et un bouton suivant en haut à droite.

let prevButtonItem = UIBarButtonItem(title: "\u{25C0}", style: .plain, target: self, action: #selector(prevButtonTapped))
let nextButtonItem = UIBarButtonItem(title: "\u{25B6}", style: .plain, target: self, action: #selector(nextButtonTapped))
self.navigationItem.rightBarButtonItems = [nextButtonItem, prevButtonItem]

Swift

// create button
    var backButton = UIButton(type: 101)

    // left-pointing shape!
    backButton.addTarget(self, action: #selector(self.backAction), for: .touchUpInside)
    backButton.setTitle("Back", for: .normal)

    // create button item -- possible because UIButton subclasses UIView!
    var backItem = UIBarButtonItem(customView: backButton)

    // add to toolbar, or to a navbar (you should only have one of these!)
    toolbar.items = [backItem]
    navItem.leftBarButtonItem = backItem

Essayez ceci. Je suis sûr que vous n’avez pas besoin d’une image de bouton arrière pour en créer une.

UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back"
                                                               style:UIBarButtonItemStyleBordered
                                                              target:self
                                                              action:@selector(yourSelectorGoesHere:)];
self.navigationItem.backBarButtonItem = backButton;

C'est tout ce que vous avez à faire:)

Pourquoi faites-vous cela? Si vous voulez quelque chose qui ressemble à une barre de navigation, utilisez UINavigationBar.

Un style visuel spécifique est associé aux barres d’outils. Les instructions d'interface utilisateur pour l'état de l'iPhone:

  

Une barre d’outils apparaît dans la partie inférieure de l’écran et contient des boutons permettant d’exécuter des actions liées aux objets de la vue actuelle.

Il donne ensuite plusieurs exemples visuels d’icônes grossièrement carrées sans texte. Je vous exhorte à suivre le HIG à ce sujet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top