Kartennavigation

Die meisten kartenbasierten Add-ons werden mit mehreren Karten erstellt, die verschiedene „Seiten“ der Add-on-Schnittstelle darstellen. Für eine effektive User Experience sollten Sie in Ihrem Add-on eine einfache und natürliche Navigation zwischen den Karten verwenden.

Ursprünglich in Gmail-Add-ons werden Übergänge zwischen verschiedenen Karten der Benutzeroberfläche gehandhabt, indem Karten in einen einzelnen Kartenstapel gezogen und daraus entfernt werden, wobei die obere Karte des Stapels in Gmail angezeigt wird.

Navigation auf Startseitenkarte

Mit den Google Workspace-Add-ons werden Startseiten und nicht kontextbezogene Karten eingeführt. Für kontextbezogene und nicht kontextbezogene Karten gibt es für Google Workspace-Add-ons jeweils einen internen Kartenstapel. Wenn ein Add-on in einem Host geöffnet wird, wird die entsprechende homepageTrigger ausgelöst, um die erste Startseitenkarte im Stapel zu erstellen (im folgenden Diagramm die dunkelblaue Startseitenkarte). Wenn keine homepageTrigger definiert ist, wird eine Standardkarte erstellt, angezeigt und in den nicht kontextbezogenen Stapel verschoben. Diese erste Karte ist eine Root-Karte.

Mit Ihrem Add-on können zusätzliche nicht kontextbezogene Karten erstellt und auf den Stapel verschoben werden (die blauen „Push-Karten“ im Diagramm), während der Nutzer durch das Add-on navigiert. Die Add-on-UI zeigt die oberste Karte im Stapel an. Wenn neue Karten in den Stapel verschoben werden, ändert sich die Anzeige. Wenn Karten aus dem Stapel entfernt werden, werden die vorherigen Karten wieder angezeigt.

Wenn dem Add-on ein definierter kontextbasierter Trigger zugeordnet ist, wird der Trigger ausgelöst, sobald der Nutzer diesen Kontext eingibt. Die Triggerfunktion erstellt die Kontextkarte, aber die UI-Anzeige wird basierend auf dem DisplayStyle der neuen Karte aktualisiert:

  • Wenn für DisplayStyle der Standardwert REPLACE festgelegt ist, ersetzt die Kontextkarte (die dunkelorangefarbene Kontextkarte im Diagramm) die aktuell angezeigte Karte. Dadurch wird effektiv ein neuer kontextbezogener Kartenstapel über dem nicht kontextbezogenen Kartenstapel gestartet. Diese Kontextkarte ist die Stammkarte des kontextbezogenen Stacks.
  • Wenn DisplayStyle auf PEEK gesetzt ist, wird in der UI stattdessen eine Kopfzeile erstellt, die unten in der Seitenleiste des Add-ons angezeigt wird und die aktuelle Karte überlagert. Der Peek-Header zeigt den Titel der neuen Karte an und bietet Steuerelemente für die Nutzerschaltfläche, über die der Nutzer entscheiden kann, ob er die neue Karte sehen möchte oder nicht. Wenn der Nutzer auf die Schaltfläche Anzeigen klickt, ersetzt die Karte die aktuelle Karte (wie oben durch REPLACE beschrieben).

Sie können zusätzliche Kontextkarten erstellen und auf den Stapel schieben (die gelben „Push-Karten“ im Diagramm). Beim Aktualisieren des Kartenstapels wird in der Add-on-UI die oberste Karte angezeigt. Wenn der Nutzer einen Kontext verlässt, werden die kontextbezogenen Karten aus dem Stapel entfernt und die Anzeige auf der obersten nicht kontextbezogenen Karte oder Startseite aktualisiert.

Wenn der Nutzer einen Kontext eingibt, für den Ihr Add-on keinen kontextbezogenen Trigger definiert, wird keine neue Karte erstellt und die aktuelle Karte bleibt angezeigt.

Die unten beschriebenen Navigation-Aktionen wirken sich nur auf Karten mit demselben Kontext aus. Zum Beispiel zeigt popToRoot() innerhalb einer Kontextkarte nur alle anderen kontextbezogenen Karten an und hat keine Auswirkungen auf die Startseitenkarten.

Im Gegensatz dazu kann der Nutzer immer über die Schaltfläche von Ihren kontextbezogenen Karten zu Ihren nicht kontextbezogenen Karten wechseln.

Du kannst Übergänge zwischen Karten erstellen, indem du Karten zu den Kartenstapeln hinzufügst oder daraus entfernst. Die Klasse Navigation bietet Funktionen, mit denen sich Karten per Push aus den Stapeln laden lassen. Damit Sie eine effektive Kartennavigation erstellen können, müssen Sie Ihre Widgets für die Verwendung von Navigationsaktionen konfigurieren. Sie können mehrere Karten gleichzeitig verschieben oder zusammendrücken. Die erste Startseitenkarte, die beim Start des Add-ons zuerst auf den Stapel geschoben wurde, lässt sich jedoch nicht entfernen.

So rufen Sie als Reaktion auf eine Nutzerinteraktion mit einem Widget eine neue Karte auf:

  1. Erstellen Sie ein Action-Objekt und verknüpfen Sie es mit einer von Ihnen definierten Callback-Funktion.
  2. Rufen Sie die entsprechende Widget-Handler-Funktion des Widgets auf, um Action für dieses Widget festzulegen.
  3. Implementieren Sie die Callback-Funktion, die die Navigation durchführt. Diese Funktion erhält ein Aktionsereignisobjekt als Argument und muss Folgendes tun:
    1. Erstelle ein Navigation-Objekt, um die Kartenänderung zu definieren. Ein einzelnes Navigation-Objekt kann mehrere Navigationsschritte enthalten. Diese werden in der Reihenfolge ausgeführt, in der sie dem Objekt hinzugefügt werden.
    2. Erstellen Sie ein ActionResponse-Objekt mit der Klasse ActionResponseBuilder und dem Objekt Navigation.
    3. Geben Sie den erstellten ActionResponse zurück.

Beim Erstellen von Navigationssteuerelementen können Sie die folgenden Navigation-Objektfunktionen verwenden:

Funktion Beschreibung
Navigation.pushCard(Card) Verschiebt eine Karte in den aktuellen Stapel. Dazu muss die Karte zuerst vollständig erstellt werden.
Navigation.popCard() Entfernt eine Karte oben aus dem Stapel. Entspricht dem Klicken auf den Zurück-Pfeil in der Add-on-Kopfzeile. Dadurch werden keine Root-Karten entfernt.
Navigation.popToRoot() Entfernt alle Karten mit Ausnahme der Root-Karte aus dem Stapel. Setzt diesen Kartenstapel im Wesentlichen zurück.
Navigation.popToNamedCard(String) Karten werden so lange aus dem Stapel entfernt, bis eine Karte mit dem angegebenen Namen oder der Root-Karte des Stapels angezeigt wird. Mit der Funktion CardBuilder.setName(String) können Sie Karten Namen zuweisen.
Navigation.updateCard(Card) Die aktuelle Karte wird direkt ersetzt und die Anzeige in der Benutzeroberfläche wird aktualisiert.

Wenn eine Nutzerinteraktion oder ein Ereignis dazu führen soll, dass Karten noch einmal im selben Kontext gerendert werden, verwenden Sie die Methoden Navigation.pushCard(), Navigation.popCard() und Navigation.updateCard(), um die vorhandenen Karten zu ersetzen. Wenn eine Nutzerinteraktion oder ein Nutzerereignis dazu führen soll, dass Karten in einem anderen Kontext noch einmal gerendert werden, verwenden Sie ActionResponseBuilder.setStateChanged(), um die nochmalige Ausführung des Add-ons in diesen Kontexten zu erzwingen.

Im Folgenden finden Sie Beispiele für die Navigation:

  • Wenn sich der Status der aktuellen Karte durch eine Interaktion oder ein Ereignis ändert (z. B. beim Hinzufügen einer Aufgabe zu einer Aufgabenliste), verwenden Sie updateCard().
  • Wenn eine Interaktion oder ein Ereignis weitere Details enthält oder den Nutzer zu weiteren Aktionen auffordert (z. B. durch Klicken auf den Titel eines Elements für weitere Details oder durch Drücken einer Schaltfläche zum Erstellen eines neuen Kalendertermins), können Sie mit pushCard() die neue Seite anzeigen lassen, während der Nutzer die neue Seite über die Schaltfläche „Zurück“ verlassen kann.
  • Wenn der Status einer Interaktion oder eines Ereignisses auf einer vorherigen Karte aktualisiert wird (z. B. wenn der Titel eines Elements über die Detailansicht aktualisiert wird), verwenden Sie zum Aktualisieren der vorherigen und der aktuellen Karte popCard(), popCard(), pushCard(previous) und pushCard(current).

Karten werden aktualisiert

Mit Google Workspace-Add-ons können Nutzer Ihre Karte aktualisieren, indem sie die in Ihrem Manifest registrierte Apps Script-Triggerfunktion noch einmal ausführen. Nutzer lösen diese Aktualisierung über einen Add-on-Menüpunkt aus:

Seitenleiste des Google Workspace-Add-ons

Diese Aktion wird automatisch Karten hinzugefügt, die von den Triggerfunktionen homepageTrigger oder contextualTrigger generiert werden, wie in der Manifestdatei des Add-ons angegeben (die „Roots“ der kontextbezogenen und nicht kontextbezogenen Kartenstapel).

Rückgabe mehrerer Karten

Beispiel für eine Add-on-Karte

Mit Homepage- oder kontextbezogenen Triggerfunktionen wird entweder ein einzelnes Card-Objekt oder ein Array von Card-Objekten erstellt und zurückgegeben, das in der Anwendungs-UI angezeigt wird.

Wenn nur eine Karte vorhanden ist, wird sie dem nicht kontextbezogenen oder kontextbezogenen Stack als Root-Karte hinzugefügt und in der UI der Hostanwendung wird sie angezeigt.

Wenn das zurückgegebene Array mehr als ein erstelltes Card-Objekt enthält, zeigt die Hostanwendung stattdessen eine neue Karte mit einer Liste der Header jeder Karte an. Wenn der Nutzer auf einen dieser Header klickt, wird in der UI die entsprechende Karte angezeigt.

Wenn der Nutzer eine Karte aus der Liste auswählt, wird diese Karte in den aktuellen Stapel verschoben und die Hostanwendung zeigt sie an. Über die Schaltfläche wird der Nutzer zur Kopfzeilenliste der Karte zurückgeleitet.

Diese „flache“ Kartenanordnung eignet sich gut, wenn Ihr Add-on keine Übergänge zwischen den von Ihnen erstellten Karten benötigt. In den meisten Fällen ist es jedoch besser, Kartenübergänge direkt zu definieren und festzulegen, dass die Startseite und die kontextbezogenen Triggerfunktionen ein einzelnes Kartenobjekt zurückgeben.

Beispiel

Das folgende Beispiel zeigt, wie Sie mehrere Karten mit Navigationsschaltflächen erstellen, die zwischen ihnen springen. Diese Karten können entweder dem kontextbezogenen oder nicht kontextbezogenen Stack hinzugefügt werden. Dazu wird die von createNavigationCard() zurückgegebene Karte in oder außerhalb eines bestimmten Kontexts verschoben.

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