Creazione di un pulsante freccia sinistra (come lo stile "indietro" di UINavigationBar) su una barra UITool

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

Domanda

Mi piacerebbe creare un " back " pulsante castone freccia sinistra in un UIToolbar .

Per quanto ne so, l'unico modo per ottenere uno di questi è lasciare UINavigationController alle impostazioni predefinite e ne usa uno per l'elemento della barra di sinistra. Ma non posso trovare un modo per crearne uno come UIBarButtonItem , quindi non posso crearne uno in un UIToolbar standard, anche se sono molto simili a UINavigationBar s.

Potrei crearlo manualmente con le immagini dei pulsanti, ma non riesco a trovare le immagini sorgente da nessuna parte. Hanno i bordi del canale alfa, quindi lo screenshot e il taglio non otterranno risultati molto versatili.

Qualche idea oltre lo screenshot per ogni dimensione e combinazione di colori che intendo usare?

Aggiornamento: PER FAVORE, FERMI di schivare la domanda e di suggerire che non dovrei chiederlo e dovrei usare UINavigationBar . La mia app è Instapaper Pro. Mostra solo una barra degli strumenti in basso (per risparmiare spazio e massimizzare l'area del contenuto leggibile) e desidero mettere un pulsante Indietro a forma di freccia sinistra in fondo.

Dirmi che non avrei dovuto farlo non è una risposta e certamente non merita una taglia.

È stato utile?

Soluzione

Ho usato il seguente psd che ho derivato da http://www.teehanlax.com / blog /? p = 447

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

Ho quindi appena creato un UIView personalizzato che utilizzo nella proprietà customView dell'elemento della barra degli strumenti.

Funziona bene per me.


Modifica: Come sottolineato da PrairieHippo , maralbjo ha scoperto che l'utilizzo del seguente codice semplice ha funzionato (richiede un'immagine personalizzata in bundle ) dovrebbe essere combinato con questa risposta. Quindi ecco un codice aggiuntivo:

// 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];

Altri suggerimenti

Il metodo Unicode

Penso che sia molto più semplice usare solo un carattere Unicode per portare a termine il lavoro. Puoi guardare tra le frecce cercando su Triangoli Unicode o < a href = "http://www.fileformat.info/info/unicode/block/arrows/list.htm" rel = "nofollow noreferrer"> Frecce Unicode . A partire da iOS6, Apple ha cambiato il personaggio in un personaggio emoji con un bordo. Per disabilitare il bordo aggiungo 0xFE0E Unicode Variation Selector .

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;

Il blocco di codice è solo per la demo. Funzionerebbe con qualsiasi pulsante che accetta una NSString.

Per un elenco completo dei personaggi cerca su Google il carattere Unicode e ciò che desideri. Ecco la voce per Triangolo di puntamento sinistro nero .

Risultato

Il risultato

ATTENZIONE: ci sono rapporti secondo cui questo non funzionerà su iOS 6. Questo potrebbe funzionare solo su versioni precedenti del sistema operativo. Evidentemente almeno uno sviluppatore ha rifiutato la propria app per l'utilizzo di questo trucco (vedi i commenti). Utilizzare a proprio rischio. L'uso di un'immagine (vedi la risposta sopra) potrebbe essere una soluzione più sicura.

Questo può essere fatto senza aggiungere i tuoi file immagine usando il pulsante sekr1t tipo 101 per ottenere la forma corretta. Per me il trucco era capire che avrei potuto usare initWithCustomView per creare il BarButtonItem . Personalmente avevo bisogno di questo per una barra di navigazione dinamica piuttosto che una barra degli strumenti , ma l'ho provato con una barra degli strumenti e il codice è quasi lo stesso:

// 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;

Se lo stai facendo su una barra degli strumenti dovrai modificare il modo in cui imposti gli elementi, ma ciò dipende dal resto del codice e lo lascio come esercizio per il lettore. : P Questo esempio ha funzionato per me (compilato & amp; run).

Blah blah, leggi l'HIG, non usare funzionalità non documentate e tutto il resto. Esistono solo sei tipi di pulsanti supportati e questo non è uno di questi.

inserisci qui la descrizione dell'immagine

Prima di tutto devi trovare un'immagine del pulsante Indietro. Ho usato una bella app chiamata Extractor che estrae tutta la grafica da iPhone. In iOS7 sono riuscito a recuperare l'immagine chiamata UINavigationBarBackIndicatorDefault ed era di colore nero, poiché avevo bisogno di una tinta rossa Cambio colore in rosso usando Gimp.

MODIFICA:

Come menzionato da btate nel suo commento, non è necessario cambiare il colore con l'editor di immagini. Il seguente codice dovrebbe fare il trucco:

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

Quindi ho creato una vista che contiene una imageView con quella freccia, un'etichetta con il testo personalizzato e nella parte superiore della vista ho un pulsante con un'azione. Quindi ho aggiunto una semplice animazione (dissolvenza e traduzione).

Il codice seguente simula il comportamento del pulsante Indietro, inclusa l'animazione.

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

Modifica

Invece di aggiungere il pulsante, secondo me l'approccio migliore è usare un riconoscimento dei gesti.

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

Non sono sicuro che funzioni, ma potresti provare a creare un UINavigationController con le impostazioni predefinite per creare il pulsante, trovare il pulsante nella gerarchia di visualizzazione secondaria del controller di navigazione, chiamare removeFromSuperview su di esso, distruggere il controller di navigazione e quindi aggiungere il pulsante come sottoview della barra degli strumenti. Potrebbe anche essere necessario conservare e il pulsante prima di chiamare removeFromSuperview (e quindi rilasciare dopo averlo aggiunto come sottoview della barra degli strumenti) per evitarlo essere deallocato durante il processo.

Per rendere un UIButton abbastanza vicino (non sono un designer;) alla freccia indietro del sistema iOS 7:

Standard:

Freccia posteriore del sistema standard

Apple SD Gothic Neo

Apple SD Gothic Neo <carattere

In Xcode:

  • Concentrati sul campo del valore del titolo del pulsante (o su qualsiasi altra vista / controllo con contenuto testuale)
  • Apri Modifica - > Personaggi speciali
  • Seleziona il gruppo Parentesi e fai doppio clic su "<" carattere
  • Cambia font in: Apple SD Gothic Neo, Regular con le dimensioni desiderate (ad es. 20)
  • Cambia colore come preferisci

Rif. @ staticVoidMan's answer alla freccia di tipo Back-like su iOS 7

 freccia indietro

Se non vuoi preoccuparti dei file di immagine, la forma della freccia può essere disegnata in una sottoclasse UIView con il seguente codice:

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

dove la vista a freccia è proporzionale a una larghezza di 6,0 e un'altezza di 10,0

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

Funziona per me. L'ho usato quando avevo più schede quindi potevo stare sulla barra delle schede e un controller di visualizzazione spinto da " Più " sovrascrivere leftBarButtonItem nella sua viewDidLoad.

Puoi trovare le immagini sorgente estraendole da Other.artwork in UIKit $ {SDKROOT} /System/Library/Frameworks/UIKit.framework/Other.artwork. La comunità di modding ha alcuni strumenti per estrarli, qui . Una volta estratta l'immagine, puoi scrivere del codice per ricolorarlo secondo necessità e impostarlo come immagine del pulsante. Indipendentemente dal fatto che tu possa effettivamente spedire una cosa del genere (dal momento che stai incorporando opere d'arte derivate) potrebbe essere un po 'rischioso, quindi forse vuoi parlare con un avvocato.

La libreria Three20 ha un modo per farlo:

  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;

Ho scoperto che usando il seguente semplice codice ha funzionato (richiede un'immagine personalizzata in bundle):

// 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];

Ecco cosa ho fatto dopo aver cercato tra tutte queste soluzioni e altre. Utilizza un PNG estensibile estratto dalle immagini stock di UIKit. In questo modo puoi impostare il testo su qualunque cosa tu stia mentendo

// 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;

È facile farlo con Interface Builder in Xcode 5.x

Risultato

  • usa Barra degli strumenti e Elemento pulsante barra da Libreria oggetti

    Components

  • nella sezione Impostazioni attributi modifica Immagine con la tua immagine del pulsante indietro

    Ispettore attributi

Fine

Stavo cercando di fare la stessa cosa, ma volevo che il pulsante Indietro fosse nella barra di navigazione. (In realtà avevo bisogno di un pulsante Indietro, che farebbe molto di più che tornare indietro, quindi ho dovuto usare la proprietà leftBarButtonItem). Ho provato ciò che AndrewS ha suggerito, ma nella barra di navigazione non avrebbe avuto l'aspetto che avrebbe dovuto, dato che UIButton era un po 'lanciato su un UIBarButtonItem.

Ma ho trovato un modo per aggirare questo. In realtà ho appena messo un UIView sotto l'UIButton e ho impostato il customView per l'UIBarButtonItem. Ecco il codice, se qualcuno ne ha bisogno:

// 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]];

Per creare un'immagine per UIToolbar, crea un png in Photoshop e DOVE MAI c'è QUALSIASI colore lo mette bianco, e dove è alpha = 0 allora lo lascia da solo.

L'SDK in realtà mette il bordo attorno all'icona che hai creato e lo trasforma in bianco senza che tu debba fare nulla.

Vedi, questo è ciò che ho realizzato in Photoshop per il mio pulsante Avanti (ovviamente scambiarlo con il pulsante Indietro):

http://twitpic.com/1oanv

e questo è come appariva in Interface Builder

http://twitpic.com/1oaoa

Soluzione SENZA usare un png. Sulla base di questa risposta SO: Aggiunta della piccola freccia sul lato destro di una cella in una cella TableView di iPhone

Semplicemente capovolgendo UITableViewCell in orizzontale!

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];

Se si desidera evitare di disegnarlo da soli, è possibile utilizzare la classe non documentata: UINavigationButton con stile 1. Ciò potrebbe, ovviamente, impedire l'approvazione dell'applicazione ... / John

Bene, non devi avere un pulsante diverso per ogni dimensione, puoi usare [UIImage stretchableImageWithLeftCapWidth: topCapHeight:] , ma l'unica cosa che ho trovato sono le immagini personalizzate.

Ho avuto un problema simile, e ne esco una libreria PButton . E l'esempio è il pulsante di navigazione posteriore come pulsante, che può essere utilizzato ovunque come un pulsante personalizzato.

Qualcosa del genere: inserisci qui la descrizione dell'immagine

Esempio in Swift 3, con un pulsante precedente e uno successivo in alto a destra.

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

Prova questo. Sono sicuro che non è necessaria un'immagine del pulsante Indietro per crearne una.

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

Questo è tutto ciò che devi fare :)

Perché lo stai facendo? Se vuoi qualcosa che assomigli a una barra di navigazione, usa UINavigationBar.

Le barre degli strumenti hanno uno stile visivo specifico associato ad esse. Le Linee guida per l'interfaccia umana per lo stato di iPhone:

  

Una barra degli strumenti appare sul bordo inferiore dello schermo e contiene pulsanti che eseguono azioni relative agli oggetti nella vista corrente.

Fornisce quindi diversi esempi visivi di icone approssimativamente quadrate senza testo. Vi esorto a seguire l'HIG su questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top