Kartennavigation

Die meisten Add-ons mit Kartenelementen bestehen aus mehreren Karten, die verschiedene „Seiten“ der Add-on-Benutzeroberflä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 wurden in Gmail-Add-ons Übergänge zwischen verschiedenen Karten der Benutzeroberfläche durch Ein- und Ausblenden von Karten in und aus einem einzelnen Kartenstapel gesteuert. Die oberste Karte des Stapels wurde von Gmail angezeigt.

Navigation auf der Startseitenkarte

Mit Google Workspace-Add-ons werden Startseiten und nicht kontextbezogene Karten eingeführt. Für kontextbezogene und nicht kontextbezogene Karten gibt es in 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 (die dunkelblaue Karte „Startseite“ im Diagramm unten). Wenn homepageTrigger nicht definiert ist, wird eine Standardkarte erstellt, angezeigt und in den nicht kontextbezogenen Stapel geschoben. Diese erste Karte ist eine Stammkarte.

Ihr Add-on kann zusätzliche nicht kontextbezogene Karten erstellen und sie in den Stapel (die blauen „geschobenen Karten“ im Diagramm) schieben, während sich der Nutzer durch Ihr Add-on bewegt. Auf der Benutzeroberfläche des Add-ons wird die oberste Karte im Stapel angezeigt. Wenn also neue Karten in den Stapel gelegt werden, ändert sich die Anzeige. Wenn Karten aus dem Stapel entfernt werden, werden die vorherigen Karten wieder angezeigt.

Wenn für Ihr Add-on ein kontextbezogener Trigger definiert ist, wird der Trigger ausgelöst, wenn der Nutzer diesen Kontext betritt. Die Triggerfunktion erstellt die kontextbezogene Karte, die UI-Anzeige wird jedoch basierend auf der DisplayStyle der neuen Karte aktualisiert:

  • Wenn DisplayStyle REPLACE ist (Standardeinstellung), wird die aktuell angezeigte Karte durch die kontextbezogene Karte (dunkelorange im Diagramm) ersetzt. Dadurch wird ein neuer kontextbezogener Kartenstapel über dem nicht kontextbezogenen Kartenstapel gestartet. Diese kontextbezogene Karte ist die Stammkarte des kontextbezogenen Stapels.
  • Wenn der DisplayStyle PEEK ist, wird stattdessen ein eingeblendeter Header erstellt, der unten in der Add-on-Seitenleiste erscheint und die aktuelle Karte überlagert. Die Überschrift der Vorschau enthält den Titel der neuen Karte und die Schaltflächen, mit denen Nutzer entscheiden können, ob sie die neue Karte aufrufen möchten. Wenn der Nutzer auf die Schaltfläche Anzeigen klickt, wird die aktuelle Karte durch die neue Karte ersetzt (wie oben für REPLACE beschrieben).

Sie können zusätzliche kontextbezogene Karten erstellen und auf den Stapel legen (gelbe „geschobene Karten“ im Diagramm). Wenn Sie den Kartenstapel aktualisieren, wird auf der Add-on-Benutzeroberfläche die oberste Karte angezeigt. Wenn der Nutzer einen Kontext verlässt, werden die kontextbezogenen Karten im Stapel entfernt und die Anzeige wird auf die oberste nicht kontextbezogene Karte oder Startseite aktualisiert.

Wenn der Nutzer einen Kontext eingibt, für den in Ihrem Add-on kein kontextueller Trigger definiert ist, 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. Wenn Sie beispielsweise popToRoot() in einer kontextbezogenen Karte verwenden, werden nur die anderen kontextbezogenen Karten eingeblendet. Die Startseitenkarten bleiben davon unberührt.

Die Schaltfläche  ist dagegen immer verfügbar, damit Nutzer von Ihren kontextbezogenen Karten zu Ihren nicht kontextbezogenen Karten wechseln können.

Sie können Übergänge zwischen Karten erstellen, indem Sie Karten zu den Kartenstapel hinzufügen oder daraus entfernen. Die Klasse Navigation bietet Funktionen zum Einfügen und Entfernen von Karten aus den Stapeln. Für eine effektive Kartennavigation konfigurieren Sie Ihre Widgets so, dass sie Navigationsaktionen verwenden. Sie können mehrere Karten gleichzeitig auf den Stapel legen oder entfernen. Die erste Startseitenkarte, die beim Starten des Add-ons auf den Stapel gelegt wird, kann jedoch nicht entfernt werden.

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-Handlerfunktion des Widgets auf, um die Action für das Widget festzulegen.
  3. Implementiere die Callback-Funktion, die die Navigation steuert. Diese Funktion erhält ein Ereignisobjekt vom Typ „Aktion“ als Argument und muss Folgendes tun:
    1. Erstellen Sie 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 werden.
    2. Erstellen Sie ein ActionResponse-Objekt mit der Klasse ActionResponseBuilder und dem Navigation-Objekt.
    3. Geben Sie die erstellte ActionResponse zurück.

Für Navigationssteuerelemente verwenden Sie die folgenden Navigation-Objektfunktionen:

Funktion Beschreibung
Navigation.pushCard(Card) Eine Karte wird auf den aktuellen Stapel gelegt. Dazu muss die Karte zuerst vollständig erstellt werden.
Navigation.popCard() Entfernt eine Karte von der Spitze des Stapels. Entspricht dem Klicken auf den Zurückpfeil in der Kopfzeile des Add-ons. Stammkarten werden dadurch nicht entfernt.
Navigation.popToRoot() Entfernt alle Karten aus dem Stapel mit Ausnahme der Stammkarte. Dieser Kartenstapel wird im Grunde zurückgesetzt.
Navigation.popToNamedCard(String) Entfernt Karten aus dem Stapel, bis eine Karte mit dem angegebenen Namen oder die Stammkarte des Stapels erreicht wird. Mit der Funktion CardBuilder.setName(String) können Sie Karten Namen zuweisen.
Navigation.updateCard(Card) Ersetzt die aktuelle Karte an Ort und Stelle und aktualisiert die Darstellung auf der Benutzeroberfläche.

Wenn eine Nutzerinteraktion oder ein Ereignis 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 durch eine Nutzerinteraktion oder ein Ereignis Karten in einem anderen Kontext neu gerendert werden sollen, verwenden Sie ActionResponseBuilder.setStateChanged(), um die Ausführung Ihres Add-ons in diesen Kontexten zu erzwingen.

Im Folgenden finden Sie Beispiele für Navigation:

  • Wenn durch eine Interaktion oder ein Ereignis der Status der aktuellen Karte geändert wird (z. B. wenn einer Aufgabenliste eine Aufgabe hinzugefügt wird), verwenden Sie updateCard().
  • Wenn eine Interaktion oder ein Ereignis weitere Details liefert oder den Nutzer zu einer weiteren Aktion auffordert (z. B. wenn er auf den Titel eines Artikels klickt, um weitere Details zu sehen, oder auf eine Schaltfläche drückt, um einen neuen Kalendertermin zu erstellen), verwenden Sie pushCard(), um die neue Seite anzuzeigen und dem Nutzer gleichzeitig die Möglichkeit zu geben, die neue Seite über die Schaltfläche „Zurück“ zu verlassen.
  • Wenn durch eine Interaktion oder ein Ereignis der Status einer vorherigen Karte aktualisiert wird (z. B. der Titel eines Artikels in der Detailansicht), verwenden Sie popCard(), popCard(), pushCard(previous) und pushCard(current), um die vorherige und die aktuelle Karte zu aktualisieren.

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 können diese Aktualisierung über einen Add-on-Menüpunkt auslösen:

Seitenleiste für Google Workspace-Add-ons

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

Mehrere Karten zurückgeben

Beispiel für eine Add-on-Karte

Mit Startseiten- oder Kontexttriggerfunktionen wird entweder ein einzelnes Card-Objekt oder ein Array von Card-Objekten erstellt und zurückgegeben, die in der Anwendungs-UI angezeigt werden.

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

Wenn das zurückgegebene Array mehr als ein integriertes 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 eine dieser Überschriften klickt, wird in der Benutzeroberfläche die entsprechende Karte angezeigt.

Wenn der Nutzer eine Karte aus der Liste auswählt, wird diese Karte auf den aktuellen Stapel geschoben und von der Hostanwendung angezeigt. Über die Schaltfläche  kehrt der Nutzer zur Liste der Kartenheader zurück.

Diese „flache“ Kartenanordnung kann gut funktionieren, wenn für Ihr Add-on keine Übergänge zwischen den von Ihnen erstellten Karten erforderlich sind. In den meisten Fällen ist es jedoch besser, Kartenübergänge direkt zu definieren und die Funktionen für die Startseite und die kontextbezogenen Trigger ein einzelnes Kartenobjekt zurückgeben zu lassen.

Beispiel

Hier ist ein Beispiel, das zeigt, wie Sie mehrere Karten mit Navigationsschaltflächen erstellen, mit denen Sie zwischen ihnen wechseln können. Diese Karten können entweder dem kontextbezogenen oder dem nicht kontextbezogenen Stapel hinzugefügt werden, indem die von createNavigationCard() zurückgegebene Karte in oder außerhalb eines bestimmten Kontexts gepusht wird.

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