Navigazione schede

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

In origine, nei componenti aggiuntivi di Gmail, le transizioni tra le diverse schede dell'interfaccia utente venivano gestite spingendo e facendo uscire le schede da e verso una singola serie di schede, con la scheda superiore della serie visualizzata da Gmail.

Navigazione nelle schede della home page

I componenti aggiuntivi di Google Workspace introducono home page e schede non contestuali. Per supportare le schede contestuali e non contestuali, i componenti aggiuntivi di Google Workspace hanno una serie interna di schede per ciascuna. Quando un componente aggiuntivo viene aperto in un host, viene attivato homepageTrigger corrispondente per creare la prima scheda della home page nell'elenco (la scheda "home page" blu scuro nel diagramma di seguito). Se non è definito un homepageTrigger, viene creata, visualizzata e inserita nello stack non contestuale una scheda predefinita. Questa prima scheda è una scheda principale.

Il componente aggiuntivo può creare schede non contestuali aggiuntive e inserirle nella serie (le "schede inviate" blu nel diagramma) mentre l'utente naviga nel componente aggiuntivo. L'interfaccia utente del componente aggiuntivo mostra la scheda in cima alla serie, quindi l'aggiunta di nuove schede alla serie modifica la visualizzazione e l'estrazione delle schede dalla serie fa tornare la visualizzazione alle schede precedenti.

Se il tuo componente aggiuntivo ha un attivatore contestuale definito, si attiva quando l'utente entra in quel contesto. La funzione di attivazione costruisce la scheda contestuale, ma la visualizzazione dell'interfaccia utente viene aggiornata in base al 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 pila di schede contestuali sopra la pila di schede non contestuali e questa scheda contestuale è la scheda principale della pila contestuale.
  • Se DisplayStyle è PEEK, l'interfaccia utente crea un'intestazione in primo piano che viene visualizzata nella parte inferiore della barra laterale del componente aggiuntivo, sovrapponendosi alla scheda corrente. L'intestazione della visualizzazione rapida mostra il titolo della nuova scheda e fornisce i controlli dei pulsanti che consentono all'utente di decidere se visualizzarla o meno. Se fa clic sul pulsante Visualizza, la scheda sostituisce quella corrente (come descritto sopra con REPLACE).

Puoi creare altre schede contestuali e spingerle nella serie (le "schede in primo piano" gialle nel diagramma). L'aggiornamento della serie di schede modifica l'interfaccia utente del componente aggiuntivo in modo da visualizzare la scheda più in alto. Se l'utente abbandona un contesto, le schede contestuali nella serie vengono rimosse e la visualizzazione viene aggiornata alla scheda non contestuale o alla home page 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() all'interno di una scheda contestuale fa apparire solo tutte le altre schede contestuali e non influisce sulle 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 schede dalle serie. La classe Navigation fornisce funzioni per inserire e rimuovere le schede dagli stack. Per creare una navigazione efficace tra le schede, configura i widget in modo che utilizzino le azioni di navigazione. Puoi spingere o far uscire più schede contemporaneamente, ma non puoi rimuovere la scheda della home page iniziale che viene inserita per prima nello stack all'avvio del componente aggiuntivo.

Per passare a una nuova scheda in risposta a un'interazione dell'utente con un widget:

  1. Crea un oggetto Action e associalo a una funzione di callback che definisci.
  2. Chiama la funzione di gestore del widget appropriata per impostare Action sul widget.
  3. Implementa la funzione di callback che gestisce la navigazione. A questa funzione viene fornito un oggetto evento di azione come argomento e deve eseguire le seguenti operazioni:
    1. Crea un oggetto Navigation per definire la modifica della carta. 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. Restituire il valore compilato ActionResponse.

Quando crei i controlli di navigazione, utilizza le seguenti funzioni dell'oggetto Navigation:

Funzione Descrizione
Navigation.pushCard(Card) Inserisce una scheda nell'elenco corrente. Per farlo, devi prima creare completamente la scheda.
Navigation.popCard() Rimuove una carta dalla parte superiore della serie. È equivalente 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 serie, tranne la scheda principale. In sostanza reimposta la serie di schede.
Navigation.popToNamedCard(String) Estrae le schede dalla serie finché non raggiunge una scheda con il nome specificato o la scheda principale della serie. Puoi assegnare nomi alle schede utilizzando la funzione CardBuilder.setName(String).
Navigation.updateCard(Card) Esegue una sostituzione in situ della scheda corrente, aggiornandone la visualizzazione nell'interfaccia utente.

Se un evento o un'interazione con l'utente deve comportare il rendering delle schede nello stesso contesto, utilizza i metodi Navigation.pushCard(), Navigation.popCard() e Navigation.updateCard() per sostituire le schede esistenti. Se un evento o un'interazione utente deve portare al nuovo rendering delle schede in un contesto diverso, utilizza ActionResponseBuilder.setStateChanged() per forzare la riesecuzione del componente aggiuntivo in questi contesti.

Di seguito sono riportati alcuni esempi di navigazione:

  • Se un'interazione o un evento modifica lo stato della scheda corrente (ad esempio, l'aggiunta di un'attività a un elenco di attività), utilizza updateCard().
  • Se un'interazione o un evento fornisce ulteriori dettagli o richiede all'utente un'ulteriore azione (ad esempio, fare clic sul titolo di un elemento per visualizzare ulteriori dettagli o premere un pulsante per creare un nuovo evento nel calendario), utilizza pushCard() per mostrare la nuova pagina e consentire all'utente di uscirne utilizzando il pulsante di riavvolgimento.
  • Se un'interazione o un evento aggiorna lo stato in una scheda precedente (ad esempio, l'aggiornamento del titolo di un elemento dalla visualizzazione dettagliata), utilizza qualcosa come popCard(), popCard(), pushCard(previous), e pushCard(current) per aggiornare la scheda precedente e quella corrente.

Aggiornamento delle schede

I componenti aggiuntivi di Google Workspace consentono agli utenti di aggiornare la scheda eseguendo di nuovo la funzione di attivazione di Apps Script registrata nel manifest. Gli utenti attivano questo aggiornamento tramite una voce di menu del componente aggiuntivo:

Barra laterale dei componenti aggiuntivi di Google Workspace

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

Restituzione di più carte

Scheda di esempio del componente aggiuntivo

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

Se è presente una sola scheda, viene aggiunta alla pila non contestuale o contestuale come scheda principale e viene visualizzata nell'interfaccia utente dell'applicazione host.

Se l'array restituito include più di un oggetto Card compilato, l'applicazione host mostra invece una nuova scheda contenente un elenco delle intestazioni di ogni scheda. Quando l'utente fa clic su una di queste intestazioni, la UI visualizza la scheda corrispondente.

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

Questa disposizione delle schede "piatta" può funzionare bene se il componente aggiuntivo non richiede transizioni tra le schede che crei. Tuttavia, nella maggior parte dei casi, è buona prassi 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

Di seguito è riportato 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 allo stato in base al contesto o non in base al contesto inviando 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();
  }