Inseriamo una Toolbar sopra la tastiera, la proprietà “inputAccessoryView”

Lavorando ad un’applicazione ho avuto la necessità di inserire una toolbar appena sopra la tastiera di iOS, per permettere all’utente di terminare l’inserimento di testo in una UITextField (ma si può applicare senza problemi anche ad altri componenti).

Questo comportamento viene utilizzato anche da Apple stessa, che spesso sopra la tastiera inserisce una barra (una toolbar appunto) con dei pulsanti quali “Prec.”, “Succ.”. Eccovi un esempio di ciò nell’app Safari:

Spulciando la documentazione e cercando in rete ho scoperto che esiste una proprietà che permette di implementare questa barra in maniera davvero molto veloce. Tale proprietà è “inputAccessoryView”, ed è presente, ad esempio, nelle classi UITextField e UITextView.

Per inserire questa barra dovremo semplicemente creare una UIToolbar con i pulsanti che desideriamo, e poi assegnarla come “inputAccessoryView” dell’oggetto con cui vogliamo che venga visualizzata. Il codice deve essere inserito in un metodo che viene richiamato all’inizio della modifica del componente in questione (ad es. il metodo textViewShouldBeginEditing: del protocollo UITextViewDelegate). Eccovi un esempio di codice:

- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    // creaiamo la toolbar da inserire sopra la tastiera
    UIToolbar *toolbar = [[UIToolbar alloc] init];
    toolbar.frame = CGRectMake(0, 0, self.view.frame.size.width, 44.0);
    toolbar.barStyle = UIBarStyleBlackTranslucent;

    // creiamo il bottone per terminare l'inserimento
    UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(fineInserimentoNota:)];
    UIBarButtonItem *spaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; // spazio per mantenere a dx il bottone Fine
    NSMutableArray *items = [[NSMutableArray alloc] initWithObjects:spaceButton, doneButton, nil];
    toolbar.items = items;

    // settiamo la toolbar per aprirsi con la textview
    self.textViewNote.inputAccessoryView = toolbar;

    return YES;
}

Ed eccovi il risultato finale:

Ovviamente questo è solo uno dei possibili utilizzi di questa proprietà, gli altri li lascio alla vostra fantasia 😉

Alla prossima!!

Ingegnere informatico e sviluppatore freelance, mi occupo da anni di sviluppo per iOS (ma non solo). Dal 2008 scrivo su questo piccolo blog (con qualche lunga pausa), in cui parlo di programmazione e di qualsiasi altra cosa che mi diverta.

20 comments On Inseriamo una Toolbar sopra la tastiera, la proprietà “inputAccessoryView”

  • Grazie 🙂
    sto provando ad implementarla nei miei primi esperimenti… al momento mi ritorna un errore in debug su “fineInserimentoNota” ma sto sicuramente sbagliando io essendo un niubbo 🙂 … pensavo di sostituirlo con resignFirstResponder ma non va.

  • @Michele: Il metodo “fineInserimentoNota:” è un altro metodo che avevo definito, al suo interno avevo inserito solamente [self.textViewNote resignFirstResponder], come pensavi esattamente tu 😉

  • @AndreaBusi: grazie 1000 🙂 ora funziona correttamente.
    Visto che ci sono, grazie anche per il tuo “Tutorial pratici per iOS SKD”, sia per l’opera in sé, sia per il fatto che la mantieni sempre aggiornata alle nuove release di xcode.

  • Grazie mille Michele 😉

  • @AndreaBusi: Grazie intanto per i tuoi tutorial molto utili. Sono uno dei possessori del tuo ebook. Volevo farti una domanda: ma se volessi aggiungere i pulsanti prec e succ come in safari, devo usare un segmentedControl?

  • @Marco: Ciao! Esattamente, con un segmented control ottieni quello che ti serve. Ti basterà assegnare un’azione al cambiamento di stato dell’oggetto e potrai così definire l’azione precedente o successivo 😉

  • @Andrea Busi: ho provato, ma sicuramente ho sbagliato qualcosa, ma non trovo il metodo per far andare il cursore al precedente o successivo!!! Come posso fare?

  • @Marco: Non penso ci siano dei metodi di default, io avevo gestito la cosa con due metodi miei, uno per “avanzare” di field e uno per “retrocedere”. In sostanza facevo una cosa del genere:

    if ([self.field1 isFirstResponder]) {
        [self.field2 becomeFirstResponder];
    }
    

    Questo per avanzare alla field successiva, una cosa analoga ma al contrario per tornare a quella precedente 😉

  • @Andrea, scusami se rispono solo ora..
    Il metodo da te descritto funziona alla grande per passare il controllo alla textField successiva e precedente, ma ancora non riesco a creare il segmentedControl per la barra sopra la tastiera e il metodo che di sicuro sarà un selectedItemIndex.
    Grazie ancora per gli utilissimi consigli.

  • @Andrea aggiungendo il segmentedControl all’array della toolBar, il simulatore mi da errore.. Perché?? Non ne vengo a capo..

  • Andrea
    scusa il disturbo, sono riuscito a risolvere!!!!!

  • grazie mille andrea… come sempre non deludi mai!!!

  • ciao volevo sapere se invece di stare scritto:done o previous posso scivere fine e precedente-successivo

  • @Alessando: se utilizzi il bottone di default per “done” esso verrà tradotto in automatico in base alla lingua del dispositivo. In ogni caso puoi crearti un semplice bottone e inserire il nome che preferisci!

  • Ciao scusa il disturbo ma non ho capito mi da errore su fineInserimentoNota come mai non ho capito mi di e che non è stata trovata la property
    Grazie

    • Ciao, “fineInserimentoNota:” è un metodo che devi aver definito nella tua classe. Se Xcode ti segnala un errore probabilmente hai dimenticato di definirlo oppure lo hai chiamato in modo diverso 🙂

      • Scusa sono alle prime armi devo definirlo nel file h o m
        Come devo definirlo?
        Non ho capito che azione deve fare
        Grazie scusa la rottura

        • Basta nel file .m.
          Dovrai avere un metodo come questo

          - (void)fineInserimentoNota:(id)sender {
             [self.nomeTuoField resignFirstResponder];
          }
          
        • Ciao allora io ho definito il metodo così:

          – (void)fineInserimentoNota:(id)sender {
          [self.Testo resignFirstResponder];
          }

          dove Testo è il mio uitextview definito nel fil h
          così
          ibaction uitextview *Testo;

          pero quando clikko su done nel simulatore mi crasha e su questa riga mi da l’errore:

          [self.Testo resignFirstResponder]; che non sono definite le proprety di Testo

          Ti prego aiutami non riesco a venirne a capo
          GRAZIE

        • Probabilmente sbagli ad impostare qualcosa. Qui trovi il sorgente dell’esempio 🙂
          https://www.bubidevs.net/wp-content/uploads/2012/08/TestUITextView.zip

Leave a Reply to Pietro Cancel Reply

Your email address will not be published.

Site Footer