Navigazione schede

La maggior parte dei componenti aggiuntivi basati su schede viene creata utilizzando più schede che rappresentano "pagine" diverse dell'interfaccia del componente aggiuntivo. Per un'esperienza utente efficace, devi utilizzare una navigazione semplice e naturale tra le schede del componente aggiuntivo.

Originariamente nei componenti aggiuntivi di Gmail, le transizioni tra diverse schede dell'interfaccia utente vengono gestite spostando e aprendo le schede da e verso un'unica pila di schede, in cui Gmail mostra la prima scheda della pila.

Navigazione nella scheda della home page

I componenti aggiuntivi di Google Workspace introducono home page e schede non contestuali. Per inserire schede contestuali e non contestuali, i componenti aggiuntivi di Google Workspace dispongono di un insieme di schede interno per ciascuno. Quando un componente aggiuntivo viene aperto in un host, si attiva il homepageTrigger corrispondente per creare la prima scheda home page nell'elenco (la scheda "home page" di colore blu scuro nel diagramma di seguito). Se non viene definito un homepageTrigger, viene creata, visualizzata una scheda predefinita e inserita nell'elenco non contestuale. Questa prima scheda è una scheda principale.

Il componente aggiuntivo può creare altre schede non contestuali e inserirle nell'elenco (le "schede blu" nel diagramma) mentre l'utente naviga nel componente aggiuntivo. L'interfaccia utente del componente aggiuntivo mostra la prima scheda nella pila, quindi se sposti nuove schede nella pila, la visualizzazione cambia e la visualizzazione delle schede fuori dalla pila ripristina le schede precedenti.

Se il tuo componente aggiuntivo ha un attivatore contestuale definito, l'attivatore si attiva quando l'utente inserisce tale contesto. La funzione trigger crea la scheda contestuale, ma la visualizzazione della UI viene aggiornata in base alle DisplayStyle della nuova scheda:

  • Se DisplayStyle è REPLACE (il valore predefinito), la scheda contestuale (la scheda "contestuale" arancione scuro nel diagramma) sostituisce la scheda attualmente visualizzata. In questo modo, viene avviata una nuova serie di schede contestuali sopra la pila di schede non contestuali, che è la scheda principale della pila contestuale.
  • Se DisplayStyle è PEEK, l'interfaccia utente crea invece un'intestazione visibile nella parte inferiore della barra laterale del componente aggiuntivo, sovrapposta alla scheda corrente. L'intestazione di visualizzazione mostra il titolo della nuova scheda e fornisce i controlli dei pulsanti dell'utente che consentono all'utente di decidere se visualizzare o meno la nuova scheda. Se fa clic sul pulsante Visualizza, la scheda sostituisce la scheda corrente (come descritto sopra con REPLACE).

Puoi creare schede contestuali aggiuntive e inserirle nell'elenco (le "schede gialle" nel diagramma). L'aggiornamento dell'elenco di schede cambia l'interfaccia utente del componente aggiuntivo in modo che mostri la scheda in alto. Se l'utente abbandona un contesto, le schede contestuali nell'elenco vengono rimosse e la visualizzazione viene aggiornata alla home page o alla scheda non contestuale più in alto.

Se l'utente inserisce un contesto per il quale il tuo componente aggiuntivo non definisce un attivatore contestuale, non viene creata una nuova scheda e la scheda corrente rimane visualizzata.

Le azioni Navigation descritte di seguito agiscono solo sulle schede dello stesso contesto; ad esempio, popToRoot() da una scheda contestuale mostra solo tutte le altre schede contestuali e non interessano le schede della home page.

Al contrario, il pulsante è sempre disponibile per consentire all'utente di passare dalle schede contestuali alle schede non contestuali.

Puoi creare transizioni tra le schede aggiungendo o rimuovendo le schede dai gruppi. La classe Navigation fornisce funzioni per inviare e mostrare le schede dagli stack. Per creare una navigazione delle schede efficace, devi configurare i widget in modo da utilizzare azioni di navigazione. Puoi inserire più schede contemporaneamente, ma non puoi rimuovere la scheda iniziale della home page che inizialmente viene inserita nell'elenco filtri quando viene avviato il componente aggiuntivo.

Per accedere a una nuova scheda in risposta a un'interazione dell'utente con un widget, procedi nel seguente modo:

  1. Crea un oggetto Action e associalo a una funzione di callback che definisci.
  2. Chiama la funzione di gestore widget appropriata del widget per impostare Action su quel widget.
  3. Implementa la funzione di callback che conduce la navigazione. A questa funzione viene assegnato un oggetto evento azione come argomento e deve:
    1. Crea un oggetto Navigation per definire la modifica della scheda. Un singolo oggetto Navigation può contenere più passaggi di navigazione, che vengono eseguiti nell'ordine in cui vengono aggiunti all'oggetto.
    2. Crea un oggetto ActionResponse utilizzando la classe ActionResponseBuilder e l'oggetto Navigation.
    3. Restituisci l'oggetto ActionResponse creato.

Quando crei i controlli di navigazione, puoi utilizzare le seguenti funzioni degli oggetti Navigation:

Funzione Descrizione
Navigation.pushCard(Card) Invia una carta nella pila attuale. Devi prima creare la scheda completamente.
Navigation.popCard() Rimuove una carta dalla parte superiore della pila. Equivale a fare clic sulla freccia indietro nella riga di intestazione del componente aggiuntivo. Le schede principali non vengono rimosse.
Navigation.popToRoot() Rimuove tutte le schede dalla pila, ad eccezione della scheda root. In pratica, reimposta la pila di schede.
Navigation.popToNamedCard(String) Scopre le carte dalla pila fino a quando non raggiunge una carta con il nome specificato o la carta principale della pila. Puoi assegnare i nomi alle schede utilizzando la funzione CardBuilder.setName(String).
Navigation.updateCard(Card) Consente di sostituire la carta corrente e di aggiornarne la visualizzazione nell'interfaccia utente.

Se un'interazione o un evento dell'utente dovrebbe comportare la visualizzazione di nuovo delle schede nello stesso contesto, utilizza i metodi Navigation.pushCard(), Navigation.popCard() e Navigation.updateCard() per sostituire le schede esistenti. Se un'interazione o un evento dell'utente dovrebbe portare a visualizzare nuovamente le schede in un contesto diverso, utilizza ActionResponseBuilder.setStateChanged() per forzare la riesecuzione del componente aggiuntivo in quei contesti.

Di seguito sono riportati alcuni esempi di navigazione:

  • Se un'interazione o un evento modifica lo stato della scheda corrente (ad esempio, aggiungendo un'attività a un elenco di attività), utilizza updateCard().
  • Se un'interazione o un evento fornisce ulteriori dettagli o richiede all'utente ulteriori azioni (ad esempio, fare clic sul titolo di un elemento per visualizzare ulteriori dettagli o premere un pulsante per creare un nuovo evento di Calendar), utilizza pushCard() per mostrare la nuova pagina e consentire all'utente di uscire dalla nuova pagina utilizzando il pulsante Indietro.
  • Se lo stato di un'interazione o di un evento viene aggiornato in una scheda precedente (ad esempio, l'aggiornamento del titolo di un elemento dalla visualizzazione dei dettagli), utilizza popCard(), popCard(), pushCard(previous) e pushCard(current) per aggiornare la carta precedente e quella corrente.

Aggiornamento delle schede in corso...

I componenti aggiuntivi di Google Workspace offrono agli utenti la possibilità di aggiornare la scheda eseguendo nuovamente la funzione trigger di Apps Script registrata nel file manifest. Gli utenti attivano questo aggiornamento tramite un componente aggiuntivo:

Barra laterale del componente aggiuntivo di Google Workspace

Questa azione viene aggiunta automaticamente alle schede generate dalle funzioni di attivazione di homepageTrigger o contextualTrigger, come specificato nel file manifest del componente aggiuntivo (le "root" degli insiemi di schede contestuali e non contestuali).

Restituzione di più carte

Esempio di scheda del componente aggiuntivo

Le funzioni di trigger contestuale o sulla home page vengono utilizzate per creare e restituire un singolo oggetto Card o un array di oggetti Card visualizzati nell'interfaccia utente dell'applicazione.

Se è presente una sola scheda, questa viene aggiunta allo stack non contestuale o contestuale come scheda principale e nella UI dell'applicazione host.

Se l'array restituito include più oggetti Card creati, l'applicazione host mostra invece una nuova scheda contenente un elenco dell'intestazione di ogni scheda. Quando l'utente fa clic su una di queste intestazioni, l'interfaccia utente mostra la scheda corrispondente.

Quando l'utente seleziona una scheda dall'elenco, questa viene inviata allo stack attuale e viene visualizzata dall'applicazione host. Il pulsante riporta l'utente all'elenco delle intestazioni delle schede.

Questa disposizione di schede "piatta" può essere efficace se il componente aggiuntivo non ha bisogno di transizioni tra le carte che crei. Nella maggior parte dei casi, tuttavia, è consigliabile definire direttamente le transizioni delle schede e fare in modo che la home page e le funzioni di attivazione contestuale restituiscano un singolo oggetto scheda.

Esempio

Ecco un esempio che mostra come creare diverse schede con pulsanti di navigazione che consentono di passare da una all'altra. Queste schede possono essere aggiunte alla pila contestuale o non contestuale spingendo la scheda restituita da createNavigationCard() all'interno o all'esterno di un determinato contesto.

  /**
   *  Create the top-level card, with buttons leading to each of three
   *  'children' cards, as well as buttons to backtrack and return to the
   *  root card of the stack.
   *  @return {Card}
   */
  function createNavigationCard() {
    // Create a button set with actions to navigate to 3 different
    // 'children' cards.
    var buttonSet = CardService.newButtonSet();
    for(var i = 1; i <= 3; i++) {
      buttonSet.addButton(createToCardButton(i));
    }

    // Build the card with all the buttons (two rows)
    var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle('Navigation'))
        .addSection(CardService.newCardSection()
            .addWidget(buttonSet)
            .addWidget(buildPreviousAndRootButtonSet()));
    return card.build();
  }

  /**
   *  Create a button that navigates to the specified child card.
   *  @return {TextButton}
   */
  function createToCardButton(id) {
    var action = CardService.newAction()
        .setFunctionName('gotoChildCard')
        .setParameters({'id': id.toString()});
    var button = CardService.newTextButton()
        .setText('Card ' + id)
        .setOnClickAction(action);
    return button;
  }

  /**
   *  Create a ButtonSet with two buttons: one that backtracks to the
   *  last card and another that returns to the original (root) card.
   *  @return {ButtonSet}
   */
  function buildPreviousAndRootButtonSet() {
    var previousButton = CardService.newTextButton()
        .setText('Back')
        .setOnClickAction(CardService.newAction()
            .setFunctionName('gotoPreviousCard'));
    var toRootButton = CardService.newTextButton()
        .setText('To Root')
        .setOnClickAction(CardService.newAction()
            .setFunctionName('gotoRootCard'));

    // Return a new ButtonSet containing these two buttons.
    return CardService.newButtonSet()
        .addButton(previousButton)
        .addButton(toRootButton);
  }

  /**
   *  Create a child card, with buttons leading to each of the other
   *  child cards, and then navigate to it.
   *  @param {Object} e object containing the id of the card to build.
   *  @return {ActionResponse}
   */
  function gotoChildCard(e) {
    var id = parseInt(e.parameters.id);  // Current card ID
    var id2 = (id==3) ? 1 : id + 1;      // 2nd card ID
    var id3 = (id==1) ? 3 : id - 1;      // 3rd card ID
    var title = 'CARD ' + id;

    // Create buttons that go to the other two child cards.
    var buttonSet = CardService.newButtonSet()
      .addButton(createToCardButton(id2))
      .addButton(createToCardButton(id3));

    // Build the child card.
    var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle(title))
        .addSection(CardService.newCardSection()
            .addWidget(buttonSet)
            .addWidget(buildPreviousAndRootButtonSet()))
        .build();

    // Create a Navigation object to push the card onto the stack.
    // Return a built ActionResponse that uses the navigation object.
    var nav = CardService.newNavigation().pushCard(card);
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }

  /**
   *  Pop a card from the stack.
   *  @return {ActionResponse}
   */
  function gotoPreviousCard() {
    var nav = CardService.newNavigation().popCard();
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }

  /**
   *  Return to the initial add-on card.
   *  @return {ActionResponse}
   */
  function gotoRootCard() {
    var nav = CardService.newNavigation().popToRoot();
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }