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 offrire un'esperienza utente efficace, nel componente aggiuntivo dovresti utilizzare una navigazione semplice e naturale tra le schede.

In origine, nei componenti aggiuntivi di Gmail, le transizioni tra le diverse schede dell'interfaccia utente vengono gestite spingendo e aprendo le schede da e verso un'unica pila, mentre la scheda principale viene visualizzata da Gmail.

Navigazione nelle schede della home page

I componenti aggiuntivi di Google Workspace introducono home page e schede non contestuali. Per accogliere schede contestuali e non contestuali, i componenti aggiuntivi di Google Workspace dispongono di una serie interna di schede per ciascuno. Quando un componente aggiuntivo viene aperto in un host, si attiva la homepageTrigger corrispondente per creare la prima scheda della home page nello stack (la scheda "Home page" di colore blu scuro nel diagramma seguente). Se homepageTrigger non viene definito, viene creata una scheda predefinita, visualizzata e trasferita nell'elenco non contestuale. Questa prima scheda è una principale.

Il componente aggiuntivo può creare schede aggiuntive non contestuali e inserirle in pila (le "schede trasferite" blu nel diagramma) mentre l'utente scorre il componente. L'interfaccia utente del componente aggiuntivo mostra la prima scheda dello stack; pertanto, se vengono inserite nuove schede nella pila, la visualizzazione viene modificata; se si estraggono le schede dallo stack, vengono riportate le schede precedenti.

Se il componente aggiuntivo ha un attivatore contestuale definito, l'attivatore si attiva quando l'utente inserisce tale contesto. La funzione di attivazione crea la scheda contestuale, ma la visualizzazione dell'interfaccia utente viene aggiornata in base alla DisplayStyle della nuova scheda:

  • Se la DisplayStyle è REPLACE (impostazione predefinita), la scheda contestuale (la scheda "contestuale" arancione scuro nel diagramma) sostituisce la scheda attualmente visualizzata. In questo modo, viene avviato un nuovo gruppo di schede contestuali sopra quello non contestuale e questa è la scheda principale dello stack contestuale.
  • Se DisplayStyle è PEEK, la UI crea un'intestazione breve che viene visualizzata nella parte inferiore della barra laterale del componente aggiuntivo e viene sovrapposta alla scheda corrente. L'intestazione di visualizzazione mostra il titolo della nuova scheda e fornisce i controlli relativi ai pulsanti utente che consentono loro di decidere se visualizzare o meno la nuova scheda. Se fa clic sul pulsante Visualizza, la scheda sostituisce quella attuale (come descritto sopra con REPLACE).

Puoi creare altre schede contestuali e inserirle nella pila (le "carte spinte" gialle nel diagramma). L'aggiornamento del gruppo di schede modifica l'interfaccia utente del componente aggiuntivo per visualizzare la scheda più in alto. Se l'utente lascia un contesto, le schede contestuali nello stack vengono rimosse e la visualizzazione viene aggiornata nella home page o nella 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 alcuna 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 hanno effetto sulle schede della home page.

Il pulsante , invece, è sempre disponibile per consentire all'utente di passare dalle schede contestuali a quelle non contestuali.

Puoi creare transizioni tra le schede aggiungendole o rimuovendole dalle serie. La classe Navigation fornisce funzioni per eseguire il push e lo scatto delle schede dagli stack. Per creare una navigazione delle schede efficace, devi configurare i widget per l'utilizzo delle azioni di navigazione. Puoi trasferire o estrarre più schede contemporaneamente, ma non puoi rimuovere la scheda iniziale della home page che viene trasferita per la prima volta nella pila all'avvio del componente aggiuntivo.

Per accedere a una nuova scheda in risposta a un'interazione dell'utente con un widget, segui questi passaggi:

  1. Crea un oggetto Action e associalo a una funzione di callback definita da te.
  2. Richiama la funzione gestore widget appropriata per impostare Action sul widget.
  3. Implementa la funzione di callback che esegue 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 condotti nell'ordine in cui vengono aggiunti all'oggetto.
    2. Crea un oggetto ActionResponse utilizzando la classe ActionResponseBuilder e l'oggetto Navigation.
    3. Restituire l'elemento ActionResponse creato.

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

Funzione Descrizione
Navigation.pushCard(Card) Consente di trasferire una carta al mazzo attuale. Devi prima creare la scheda completamente.
Navigation.popCard() Rimuove una carta dalla parte superiore del mazzo. Equivale a fare clic sulla Freccia indietro nella riga di intestazione del componente aggiuntivo. Le schede root non vengono rimosse.
Navigation.popToRoot() Rimuove tutte le carte dal mazzo, ad eccezione della carta principale. In pratica reimposta il mazzo di carte.
Navigation.popToNamedCard(String) Fa saltare le carte dal mazzo fino a quando non raggiunge una carta con il nome dato o la carta radice del gruppo. Puoi assegnare nomi alle schede utilizzando la funzione CardBuilder.setName(String).
Navigation.updateCard(Card) Effettua una sostituzione in loco della carta corrente, aggiornando la visualizzazione nella UI.

Se un'interazione o un evento dell'utente deve comportare di nuovo il rendering delle schede nello stesso contesto, usa i metodi Navigation.pushCard(), Navigation.popCard() e Navigation.updateCard() per sostituire le schede esistenti. Se un'interazione o un evento utente dovrebbe comportare il nuovo rendering delle 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 cambia 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 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 un'interazione o un evento aggiorna lo stato in una scheda precedente (ad esempio, l'aggiornamento del titolo di un elemento dalla visualizzazione dei dettagli), usa 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 offrono agli utenti la possibilità di aggiornare la scheda eseguendo di nuovo la funzione di attivazione di Apps Script registrata nel file 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 tuo componente aggiuntivo (le "radici" delle serie di schede contestuali e non contestuali).

Restituzione di più carte

Esempio di scheda aggiuntiva

Le funzioni della home page o di trigger contestuale vengono utilizzate per creare e restituire un singolo oggetto Card o un array di oggetti Card visualizzati nella UI 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 la mostra.

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, nell'interfaccia utente viene visualizzata la scheda corrispondente.

Quando l'utente seleziona una scheda dall'elenco, questa viene trasferita nello stack corrente e viene visualizzata dall'applicazione host. Il pulsante riporta l'utente all'elenco di intestazioni della scheda.

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

Esempio

Ecco un esempio che mostra come creare più schede con pulsanti di navigazione che vanno da una all'altra. Queste schede possono essere aggiunte all'elenco contestuale o non contestuale spostando le schede restituite da createNavigationCard() all'interno o all'esterno di un particolare 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();
  }