Nawigacja na kartach

Większość dodatków opartych na kartach tworzy wiele kart, które reprezentują różne „strony” interfejsu dodatku. Aby zadbać o wygodę użytkowników, używaj prostej i naturalnej nawigacji między kartami w dodatku.

Początkowo w dodatkach w Gmailu przejścia między różnymi kartami w interfejsie są obsługiwane przez przesuwanie i wyrzucanie kart do i z jednego stosu kart, przy czym Gmail wyświetla kartę górną.

Nawigacja na karcie strony głównej

Dodatki do Google Workspace wprowadzają strony główne i karty niekontekstowe. Aby ułatwić wyświetlanie kart kontekstowych i niekontekstowych, Dodatki do Google Workspace mają wewnętrzny stos kart dla każdego z nich. Gdy dodatek jest otwierany na hoście, uruchamia się odpowiedni homepageTrigger, aby utworzyć na stosie pierwszą kartę strony głównej (na diagramie poniżej to ciemnoniebieska karta „strona główna”). Jeśli homepageTrigger nie jest zdefiniowany, tworzona jest karta domyślna, wyświetlana i przekazywana na stos niekontekstowy. Pierwsza karta jest kartą główną.

Dodatek może tworzyć dodatkowe karty niekontekstowe i przesuwać je na stos (niebieskie „przesunięte karty” na diagramie), gdy użytkownik porusza się po dodatku. Interfejs dodatku wyświetla górną kartę w stosie, więc przeniesienie nowych kart do stosu zmienia ich wygląd. Z kolei odsunięcie kart ze stosu przywraca ich poprzednie karty.

Jeśli dodatek ma zdefiniowaną regułę kontekstową, uruchomienie reguły nastąpi po wpisaniu przez użytkownika odpowiedniego kontekstu. Funkcja aktywatora tworzy kartę kontekstową, ale interfejs użytkownika jest aktualizowany na podstawie DisplayStyle nowej karty:

  • Jeśli DisplayStyle to REPLACE (domyślna), karta kontekstowa (ciemnopomarańczowa „kontekstowa” na diagramie) zastępuje aktualnie wyświetlaną kartę. Powoduje to uruchomienie nowego stosu kart kontekstowych na stosie niekontekstowym, który jest kartą główną stosu kontekstowego.
  • Jeśli DisplayStyle to PEEK, interfejs zamiast tego tworzy szybki nagłówek, który pojawia się u dołu paska bocznego dodatku, zasłaniając bieżącą kartę. Nagłówek podglądu zawiera tytuł nowej karty i zawiera przyciski użytkownika, za pomocą których mogą oni zdecydować, czy chcą ją wyświetlić. Jeśli kliknie przycisk Wyświetl, karta zastąpi bieżącą kartę (zgodnie z opisem powyżej REPLACE).

Możesz tworzyć dodatkowe karty kontekstowe i umieszczać je na stosie (żółte „przesunięte karty” na diagramie). Zaktualizowanie stosu kart powoduje, że interfejs dodatku wyświetla kartę najwyższego poziomu. Jeśli użytkownik pozostawi kontekst, karty kontekstowe na stosie zostaną usunięte, a środowisko displayowe przełączy się na kartę niekontekstową lub stronę główną znajdującą się najwyżej.

Jeśli użytkownik poda kontekst, dla którego dodatek nie definiuje aktywatora kontekstowego, nowa karta nie zostanie utworzona, a bieżąca karta pozostanie wyświetlana.

Opisane poniżej działania Navigation działają tylko na kartach w tym samym kontekście, np. z karty kontekstowej popToRoot() wyświetlają się tylko pozostałe karty kontekstowe. Nie mają one wpływu na karty na stronie głównej.

Za pomocą przycisku użytkownik zawsze może przejść z kart kontekstowych do kart niekontekstowych.

Możesz przejść między kartami, dodając je do stosów kart lub usuwając je ze stosów. Klasa Navigation udostępnia funkcje do wypychania i wydzielania kart ze stosów. Aby utworzyć efektywną nawigację po kartach, skonfiguruj widżety pod kątem działań nawigacyjnych. Możesz umieścić lub wstawić wiele kart jednocześnie, ale nie możesz usunąć początkowej karty strony głównej, która jest najpierw przekazywana na stos po uruchomieniu dodatku.

Aby przejść do nowej karty w odpowiedzi na interakcję użytkownika z widżetem, wykonaj te czynności:

  1. Utwórz obiekt Action i powiąż go ze zdefiniowaną przez siebie funkcją wywołania zwrotnego.
  2. Wywołaj odpowiednią funkcję obsługi widżetu, aby ustawić dla niego Action.
  3. Zaimplementuj funkcję wywołania zwrotnego, która przeprowadza nawigację. Ta funkcja otrzymuje jako argument obiekt zdarzenia działania i musi wykonywać te czynności:
    1. Utwórz obiekt Navigation, aby określić zmianę karty. Pojedynczy obiekt Navigation może zawierać wiele kroków nawigacji, które są wykonywane w kolejności, w jakiej są dodawane do obiektu.
    2. Utwórz obiekt ActionResponse za pomocą klasy ActionResponseBuilder i obiektu Navigation.
    3. Zwróć utworzony obiekt ActionResponse.

Podczas tworzenia elementów sterujących nawigacji korzystasz z tych funkcji obiektów Navigation:

Funkcja Opis
Navigation.pushCard(Card) Wypycha kartę na bieżący stos. W tym celu musisz najpierw w pełni utworzyć kartę.
Navigation.popCard() Usuwa 1 kartę z góry stosu. Odpowiednik kliknięcia strzałki wstecz w wierszu nagłówka dodatku. Nie spowoduje to usunięcia kart głównych.
Navigation.popToRoot() Usuwa ze stosu wszystkie karty oprócz karty głównej. Resetuje stos kart.
Navigation.popToNamedCard(String) Odsłania karty ze stosu, aż dotrze do karty o podanej nazwie lub karty głównej stosu. Możesz przypisać nazwy do kart za pomocą funkcji CardBuilder.setName(String).
Navigation.updateCard(Card) Wykonuje zamiennik bieżącej karty, odświeżając ją w interfejsie użytkownika.

Jeśli interakcja lub zdarzenie użytkownika powinny skutkować ponownym wyrenderowaniem kart w tym samym kontekście, zastąp obecne karty metodami Navigation.pushCard(), Navigation.popCard() i Navigation.updateCard(). Jeśli interakcja lub zdarzenie użytkownika powinny skutkować ponownym wyrenderowaniem kart w innym kontekście, użyj ActionResponseBuilder.setStateChanged(), aby wymusić ponowne uruchomienie dodatku w tych kontekstach.

Oto przykłady nawigacji:

  • Jeśli interakcja lub zdarzenie zmieni stan bieżącej karty (np. dodanie zadania do listy zadań), użyj właściwości updateCard().
  • Jeśli interakcja lub zdarzenie zawiera więcej szczegółów lub zachęci użytkownika do wykonania dalszych czynności (np. kliknięcia tytułu elementu, aby zobaczyć więcej szczegółów lub kliknięcia przycisku, aby utworzyć nowe wydarzenie w Kalendarzu), możesz wyświetlić nową stronę za pomocą metody pushCard(), a jednocześnie umożliwić użytkownikowi opuszczenie nowej strony przy użyciu przycisku Wstecz.
  • Jeśli interakcja lub zdarzenie zostanie zaktualizowane na poprzedniej karcie (np. aktualizacja tytułu elementu z poziomu widoku szczegółów), użyj elementów takich jak popCard(), popCard(), pushCard(previous) czy pushCard(current), aby zaktualizować poprzednią kartę i bieżącą kartę.

Odświeżam karty

Dodatki do Google Workspace umożliwiają użytkownikom odświeżenie karty przez ponowne uruchomienie funkcji aktywatora Apps Script zarejestrowanej w pliku manifestu. Użytkownicy wywołują odświeżenie za pomocą elementu menu dodatku:

Pasek boczny dodatku do Google Workspace

To działanie jest automatycznie dodawane do kart generowanych przez funkcje aktywujące homepageTrigger lub contextualTrigger, zgodnie z plikiem manifestu dodatku (elementami głównymi stosu kart kontekstowych i niekontekstowych).

Zwracanie wielu kart

Przykładowa karta dodatku

Funkcje aktywujące na stronie głównej lub kontekstowych służą do tworzenia i zwracania pojedynczych obiektów Card lub tablicy obiektów Card wyświetlanych w interfejsie aplikacji.

Jeśli jest tylko 1 karta, jest dodawana do stosu niekontekstowego lub kontekstowego, gdy karta główna wyświetla się w interfejsie aplikacji hosta.

Jeśli zwrócona tablica zawiera więcej niż 1 skompilowany obiekt Card, aplikacja hosta wyświetla nową kartę, która zawiera listę nagłówków poszczególnych kart. Gdy użytkownik kliknie dowolny z tych nagłówków, w interfejsie użytkownika pojawi się odpowiednia karta.

Gdy użytkownik wybierze kartę z listy, zostanie ona przeniesiona na bieżący stos, a aplikacja hostująca ją wyświetli. Za pomocą przycisku użytkownik widzi listę nagłówków kart.

Takie „płaskie” układ kart sprawdzi się dobrze, jeśli dodatek nie wymaga żadnych przejść między kartami. W większości przypadków lepiej jednak bezpośrednio definiować przejścia kart oraz ustawić, aby strona główna i funkcje aktywatorów kontekstowych zwracały pojedynczy obiekt karty.

Przykład

Oto przykład, który pokazuje, jak utworzyć kilka kart z przewijanymi przyciskami nawigacji. Karty te można dodawać do stosu kontekstowego lub niekontekstowego, przesuwając kartę zwracaną przez funkcję createNavigationCard() w konkretnym kontekście lub poza nim.

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