Kartennavigation

Die meisten kartenbasierten Add-ons werden mit mehreren Karten erstellt, die verschiedene „Seiten“ der Add-on-Oberfläche darstellen. Für eine effektive Nutzererfahrung 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 durch Verschieben und Verschieben von Karten in einen einzelnen Kartenstapel bzw. von einem einzelnen Kartenstapel übernommen, wobei die oberste Karte des Stapels von Gmail angezeigt wird.

Navigation auf der Startseitenkarte

Mit Add-ons für Google Workspace werden Startseiten und Karten ohne Kontext eingeführt. Um kontextbezogene und nicht kontextbezogene Karten zu berücksichtigen, hat Google Workspace-Add-ons jeweils einen internen Kartenstapel. Wenn ein Add-on auf einem Host geöffnet wird, wird die entsprechende homepageTrigger ausgelöst, um die erste Startseitenkarte im Stapel zu erstellen (die dunkelblaue Karte „Startseite“ im Diagramm unten). Wenn keine homepageTrigger definiert ist, wird eine Standardkarte erstellt, angezeigt und in den nicht kontextbezogenen Stapel verschoben. Die erste Karte ist eine Stammkarte.

Ihr Add-on kann zusätzliche nicht kontextbezogene Karten erstellen und in den Stapel verschieben (die blauen "Push-Karten" im Diagramm), während der Nutzer durch Ihr Add-on navigiert. Die Add-on-Benutzeroberfläche zeigt die oberste Karte im Stapel an. Wenn neue Karten in den Stapel verschoben werden, ändert sich die Anzeige. Wenn Sie Karten aus dem Stapel entfernen, wird die Anzeige zu den vorherigen Karten zurückgeführt.

Wenn Ihr Add-on einen definierten kontextbasierten Trigger hat, wird der Trigger ausgelöst, wenn der Nutzer diesen Kontext eingibt. Die Triggerfunktion erstellt die Kontextkarte, aber die UI-Anzeige wird anhand des DisplayStyle der neuen Karte aktualisiert:

  • Wenn DisplayStyle REPLACE (Standardeinstellung) ist, ersetzt die Kontextkarte (die dunkelorangefarbene „kontextuale“ Karte im Diagramm) die aktuell angezeigte Karte. Dadurch wird quasi ein neuer Kontextkartenstack über dem nicht kontextbezogenen Kartenstapel gestartet und diese kontextbezogene Karte ist die Stammkarte des Kontextstacks.
  • Wenn DisplayStyle auf PEEK gesetzt ist, wird in der UI stattdessen ein eingeblendeter Header erstellt, der unten in der Add-on-Seitenleiste über der aktuellen Karte eingeblendet wird. Der Peek-Header zeigt den Titel der neuen Karte an und bietet den Nutzern Schaltflächen, mit denen sie entscheiden können, ob sie die neue Karte ansehen möchten oder nicht. Wenn er auf die Schaltfläche Ansehen klickt, ersetzt die Karte die aktuelle Karte (wie oben durch REPLACE beschrieben).

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

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 aus demselben Kontext aus. Beispielsweise werden mit popToRoot() innerhalb einer Kontextkarte nur alle anderen Kontextkarten eingeblendet und wirken sich nicht auf Startseitenkarten aus.

Die Schaltfläche steht dem Nutzer hingegen immer zur Verfügung, um von Ihren Kontextkarten zu Ihren nicht kontextbezogenen Karten zu wechseln.

Sie können Übergänge zwischen Karten erstellen, indem Sie Karten zu den Kartenstapeln hinzufügen oder daraus entfernen. Die Klasse Navigation bietet Funktionen zum Verschieben und Herausnehmen von Karten aus dem Stapel. Für eine effektive Kartennavigation konfigurieren Sie Ihre Widgets für die Verwendung von Navigationsaktionen. Sie können mehrere Karten gleichzeitig verschieben oder hineinziehen, aber Sie können nicht die ursprüngliche Startseitenkarte entfernen, die beim Start des Add-ons zuerst auf den Stapel geschoben wird.

So navigieren Sie als Reaktion auf eine Nutzerinteraktion mit einem Widget zu einer neuen Karte:

  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. Dieser Funktion wird ein Aktionsereignisobjekt als Argument übergeben. Sie muss Folgendes tun:
    1. Erstelle ein Navigation-Objekt, um die Kartenänderung zu definieren. Ein einzelnes Navigation-Objekt kann mehrere Navigationsschritte enthalten, die in der Reihenfolge ausgeführt werden, in der sie dem Objekt hinzugefügt wurden.
    2. Erstellen Sie ein ActionResponse-Objekt mit der Klasse ActionResponseBuilder und dem Navigation-Objekt.
    3. Geben Sie den erstellten ActionResponse zurück.

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

Funktion Beschreibung
Navigation.pushCard(Card) Setzt eine Karte auf den aktuellen Stapel Dazu muss die Karte zuerst vollständig erstellt werden.
Navigation.popCard() Entfernt eine Karte vom oberen Rand des Stapels Entspricht dem Klicken auf den Zurückpfeil in der Kopfzeile des Add-ons. Dadurch werden keine Stammkarten entfernt.
Navigation.popToRoot() Entfernt alle Karten mit Ausnahme der Stammkarte vom Stapel. Im Wesentlichen wird dieser Kartenstapel zurückgesetzt.
Navigation.popToNamedCard(String) Ziehe Karten aus dem Stapel, bis sie eine Karte mit dem angegebenen Namen oder der Stammkarte des Stapels erreicht. Mit der Funktion CardBuilder.setName(String) können Sie Karten Namen zuweisen.
Navigation.updateCard(Card) Die aktuelle Karte wird direkt ersetzt und die Anzeige auf der Benutzeroberfläche wird aktualisiert.

Wenn eine Nutzerinteraktion oder ein Nutzerereignis dazu führen soll, dass Karten im selben Kontext neu 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 neu gerendert werden, verwenden Sie ActionResponseBuilder.setStateChanged(), um die erneute Ausführung des Add-ons in diesen Kontexten zu erzwingen.

Hier einige Navigationsbeispiele:

  • Wenn sich der Status der aktuellen Karte durch eine Interaktion oder ein Ereignis ändert (z. B. durch Hinzufügen einer Aufgabe zu einer Aufgabenliste), verwenden Sie updateCard().
  • Wenn eine Interaktion oder ein Termin weitere Details liefert oder den Nutzer zu weiteren Aktionen auffordert (z. B. auf den Titel eines Elements klicken, um weitere Details zu sehen, oder auf eine Schaltfläche klicken, um einen neuen Kalendertermin zu erstellen), kannst du pushCard() verwenden, um die neue Seite aufzurufen und dem Nutzer die Möglichkeit zu geben, die neue Seite mit der Schaltfläche „Zurück“ zu verlassen.
  • 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 etwas wie popCard(), popCard(), pushCard(previous) und pushCard(current), um die vorherige Karte und die aktuelle Karte zu aktualisieren.

Karten werden aktualisiert

Mit Add-ons für Google Workspace 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 den Karten hinzugefügt, die von den Triggerfunktionen homepageTrigger oder contextualTrigger generiert wurden, wie in der Manifestdatei des Add-ons angegeben (den „Stamm“ der kontextabhängigen und nicht kontextbezogenen Kartenstacks).

Mehrere Karten zurückgeben

Beispiel für Add-on-Karte

Startseiten- oder kontextbezogene Triggerfunktionen werden verwendet, um ein einzelnes Card-Objekt oder ein Array von Card-Objekten zu erstellen und zurückzugeben, die in der Anwendungs-UI angezeigt werden.

Wenn nur eine Karte vorhanden ist, wird diese dem nicht kontextbezogenen oder kontextbezogenen Stack als Stammkarte hinzugefügt und auf der Benutzeroberfläche der Hostanwendung angezeigt.

Wenn das zurückgegebene Array mehr als ein erstelltes Card-Objekt enthält, zeigt die Hostanwendung stattdessen eine neue Karte an, die eine Liste der Header jeder Karte enthält. 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 auf den aktuellen Stapel verschoben und von der Hostanwendung angezeigt. Über die Schaltfläche kehrt der Nutzer zur Liste mit den Kartenheadern zurück.

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

Beispiel

Das folgende Beispiel zeigt, wie du mehrere Karten mit Navigationsschaltflächen konstruierst, die zwischen ihnen wechseln können. Diese Karten können entweder dem kontextbezogenen oder nicht kontextbezogenen Stapel 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();
  }