Thao tác trên thẻ

Hầu hết các tiện ích bổ sung dựa trên thẻ được xây dựng bằng nhiều thẻ đại diện cho các "trang" khác nhau của giao diện tiện ích bổ sung. Để mang lại trải nghiệm hiệu quả cho người dùng, bạn nên sử dụng phương thức điều hướng đơn giản và tự nhiên giữa các thẻ trong tiện ích bổ sung.

Ban đầu, trong các tiện ích bổ sung của Gmail, quá trình chuyển đổi giữa các thẻ của giao diện người dùng khác nhau được xử lý bằng cách đẩy và bật thẻ lên và qua một ngăn xếp thẻ, với thẻ trên cùng của ngăn xếp được Gmail hiển thị.

Thao tác trên thẻ trang chủ

Google Workspace Tiện ích bổ sung giới thiệu trang chủ và thẻ không theo ngữ cảnh. Để phù hợp với thẻ theo ngữ cảnh và không theo ngữ cảnh, Google Workspace Tiện ích bổ sung có ngăn xếp thẻ nội bộ cho mỗi thẻ. Khi một tiện ích bổ sung được mở trong một máy chủ lưu trữ, homepageTrigger tương ứng sẽ kích hoạt để tạo thẻ trang chủ đầu tiên trên ngăn xếp (thẻ "trang chủ" màu xanh dương đậm trong sơ đồ bên dưới). Nếu không xác định homepageTrigger, thì thẻ mặc định sẽ được tạo, hiển thị và đẩy vào ngăn xếp không theo ngữ cảnh. Thẻ đầu tiên này là thẻ gốc.

Tiện ích bổ sung của bạn có thể tạo thêm các thẻ không theo ngữ cảnh và đẩy các thẻ đó vào ngăn xếp (các "thẻ được đẩy" màu xanh lam trong sơ đồ) khi người dùng di chuyển qua tiện ích bổ sung của bạn. Giao diện người dùng tiện ích bổ sung hiển thị thẻ trên cùng trong ngăn xếp, vì vậy, việc đẩy thẻ mới vào ngăn xếp sẽ thay đổi màn hình và làm nổi bật thẻ ra khỏi ngăn xếp, trả lại màn hình về thẻ trước đó.

Nếu tiện ích bổ sung của bạn có một trình kích hoạt ngữ cảnh được xác định, thì khi người dùng nhập ngữ cảnh đó, trình kích hoạt sẽ kích hoạt. Hàm kích hoạt sẽ xây dựng thẻ ngữ cảnh, nhưng màn hình giao diện người dùng sẽ được cập nhật dựa trên DisplayStyle của thẻ mới:

  • Nếu DisplayStyleREPLACE (thẻ mặc định), thì thẻ ngữ cảnh (thẻ "ngữ cảnh" màu cam đậm trong sơ đồ) sẽ thay thế thẻ hiện đang hiển thị. Cách này giúp bắt đầu hiệu quả một ngăn xếp thẻ theo ngữ cảnh mới ở đầu ngăn xếp thẻ không theo ngữ cảnh và thẻ theo ngữ cảnh này là thẻ gốc của ngăn xếp thẻ theo ngữ cảnh.
  • Nếu DisplayStylePEEK, thì giao diện người dùng sẽ tạo một tiêu đề xem trước xuất hiện ở cuối thanh bên tiện ích bổ sung, phủ lên thẻ hiện tại. Tiêu đề xem trước hiển thị tiêu đề của thẻ mới và cung cấp các nút điều khiển của nút người dùng để cho phép họ quyết định có xem thẻ mới hay không. Nếu người dùng nhấp vào nút Xem, thẻ sẽ thay thế thẻ hiện tại (như mô tả ở trên bằng REPLACE).

Bạn có thể tạo thêm các thẻ ngữ cảnh và đẩy thẻ đó vào ngăn xếp ("thẻ được đẩy" màu vàng trong sơ đồ). Việc cập nhật ngăn xếp thẻ sẽ thay đổi giao diện người dùng của tiện ích bổ sung để hiển thị thẻ trên cùng. Nếu người dùng rời khỏi một ngữ cảnh, thì các thẻ ngữ cảnh trên ngăn xếp sẽ bị xóa và màn hình hiển thị sẽ cập nhật thành thẻ hoặc trang chủ không theo ngữ cảnh ở trên cùng.

Nếu người dùng nhập ngữ cảnh mà tiện ích bổ sung của bạn không xác định trình kích hoạt theo ngữ cảnh, thì sẽ không có thẻ mới nào được tạo và thẻ hiện tại sẽ vẫn hiển thị.

Các thao tác Navigation được mô tả dưới đây chỉ hoạt động trên các thẻ có cùng ngữ cảnh; ví dụ: popToRoot() từ trong một thẻ ngữ cảnh chỉ hiển thị tất cả các thẻ theo ngữ cảnh khác và sẽ không ảnh hưởng đến thẻ trên trang chủ.

Ngược lại, nút luôn có sẵn để người dùng di chuyển từ thẻ theo ngữ cảnh đến thẻ không theo ngữ cảnh.

Bạn có thể tạo chuyển đổi giữa các thẻ bằng cách thêm hoặc xóa thẻ khỏi ngăn xếp thẻ. Lớp Navigation cung cấp các hàm để đẩy và bật thẻ từ ngăn xếp. Để tạo điều hướng hiệu quả cho thẻ, bạn hãy định cấu hình các tiện ích để sử dụng thao tác điều hướng. Bạn có thể đẩy hoặc bật nhiều thẻ cùng lúc, nhưng không thể xoá thẻ trang chủ ban đầu được đẩy vào ngăn xếp lần đầu khi tiện ích bổ sung bắt đầu.

Để chuyển đến một thẻ mới phản hồi tương tác của người dùng với một tiện ích, hãy làm theo các bước sau:

  1. Tạo một đối tượng Action và liên kết đối tượng đó với hàm gọi lại do bạn xác định.
  2. Hãy gọi hàm xử lý tiện ích thích hợp của tiện ích để đặt Action trên tiện ích đó.
  3. Triển khai hàm gọi lại để thực hiện việc điều hướng. Hàm này cung cấp một đối tượng sự kiện hành động làm đối số và phải thực hiện những việc sau:
    1. Tạo đối tượng Navigation để xác định việc thay đổi thẻ. Một đối tượng Navigation có thể chứa nhiều bước điều hướng được thực hiện theo thứ tự thêm vào đối tượng.
    2. Tạo đối tượng ActionResponse bằng cách sử dụng lớp ActionResponseBuilder và đối tượng Navigation.
    3. Trả về ActionResponse đã tạo.

Khi xây dựng các thành phần điều khiển, bạn sẽ sử dụng các hàm đối tượng Navigation sau đây:

Chức năng Mô tả
Navigation.pushCard(Card) Đẩy thẻ vào ngăn xếp hiện tại. Trước tiên, bạn cần xây dựng thẻ hoàn toàn.
Navigation.popCard() Xóa một thẻ khỏi đầu ngăn xếp. Tương đương với việc nhấp vào mũi tên quay lại trong hàng tiêu đề tiện ích bổ sung. Thao tác này không xóa các thẻ gốc.
Navigation.popToRoot() Xóa tất cả các thẻ khỏi ngăn xếp, ngoại trừ thẻ gốc. Về cơ bản, hãy đặt lại ngăn xếp thẻ đó.
Navigation.popToNamedCard(String) Kéo các thẻ từ ngăn xếp cho đến khi đạt đến thẻ có tên hoặc thẻ gốc của ngăn xếp. Bạn có thể chỉ định tên cho các thẻ bằng hàm CardBuilder.setName(String).
Navigation.updateCard(Card) Thực hiện việc thay thế tại chỗ của thẻ hiện tại, làm mới thẻ hiển thị trong giao diện người dùng.

Nếu một lượt tương tác hoặc sự kiện của người dùng dẫn đến việc hiển thị lại các thẻ trong cùng một ngữ cảnh, hãy sử dụng các phương thức Navigation.pushCard(), Navigation.popCard()Navigation.updateCard() để thay thế các thẻ hiện có. Nếu một lượt tương tác hoặc sự kiện của người dùng dẫn đến việc kết xuất lại thẻ trong một ngữ cảnh khác, hãy sử dụng ActionResponseBuilder.setStateChanged() để buộc thực thi lại tiện ích bổ sung trong những bối cảnh đó.

Sau đây là các ví dụ về điều hướng:

  • Nếu một lượt tương tác hoặc sự kiện thay đổi trạng thái của thẻ hiện tại (ví dụ: thêm một việc cần làm vào danh sách việc cần làm), hãy sử dụng updateCard().
  • Nếu một lượt tương tác hoặc sự kiện cung cấp thêm thông tin chi tiết hoặc nhắc người dùng thực hiện thao tác khác (ví dụ: nhấp vào tiêu đề của một mục để xem thêm thông tin chi tiết hoặc nhấn một nút để tạo sự kiện mới trên Lịch), hãy sử dụng pushCard() để hiển thị trang mới trong khi cho phép người dùng thoát khỏi trang mới bằng cách sử dụng nút quay lại.
  • Nếu một lượt tương tác hoặc sự kiện cập nhật trạng thái trong thẻ trước đó (ví dụ: cập nhật tiêu đề của mặt hàng từ chế độ xem chi tiết), hãy sử dụng những nội dung như popCard(), popCard(), pushCard(previous), và pushCard(current) để cập nhật thẻ trước đó và thẻ hiện tại.

Đang làm mới thẻ

Google Workspace tiện ích bổ sung cho phép người dùng làm mới thẻ của bạn bằng cách chạy lại hàm kích hoạt Apps Script đã đăng ký trong tệp kê khai. Người dùng kích hoạt quá trình làm mới này thông qua một mục trong trình đơn bổ sung:

 thanh bên tiện ích bổ sungGoogle Workspace  thanh bên tiện ích bổ sungGoogle Workspace





Hành động này được tự động thêm vào các thẻ do hàm kích hoạt homepageTrigger hoặc contextualTrigger tạo ra, như được chỉ định trong tệp kê khai của tiện ích bổ sung (phần "gốc" của ngăn xếp thẻ theo bối cảnh và không theo ngữ cảnh).

Trả nhiều thẻ

Ví dụ về thẻ tiện ích bổ sung

Các hàm kích hoạt theo trang chủ hoặc ngữ cảnh được dùng để tạo và trả về một đối tượng Card hoặc một mảng đối tượng Card mà giao diện người dùng của ứng dụng hiển thị.

Nếu chỉ có một thẻ, thẻ này sẽ được thêm vào ngăn xếp không theo ngữ cảnh hoặc ngăn ngữ cảnh như thẻ gốc và giao diện người dùng của ứng dụng lưu trữ sẽ hiển thị thẻ đó.

Nếu mảng được trả về bao gồm nhiều đối tượng Card được tạo, thì ứng dụng lưu trữ sẽ hiển thị một thẻ mới, trong đó có chứa danh sách tiêu đề của từng thẻ. Khi người dùng nhấp vào bất kỳ tiêu đề nào trong số đó, giao diện người dùng sẽ hiển thị thẻ tương ứng.

Khi người dùng chọn một thẻ trong danh sách, thẻ đó sẽ được đẩy vào ngăn xếp hiện tại và ứng dụng lưu trữ sẽ hiển thị thẻ đó. Nút đưa người dùng trở về danh sách tiêu đề thẻ.

Cách sắp xếp thẻ " Phẳng" này có thể hoạt động tốt nếu tiện ích bổ sung của bạn không cần chuyển đổi giữa các thẻ bạn tạo. Tuy nhiên, trong hầu hết các trường hợp, bạn nên xác định trực tiếp quá trình chuyển đổi thẻ, đồng thời yêu cầu trang chủ và các hàm kích hoạt theo ngữ cảnh trả về một đối tượng thẻ duy nhất.

Ví dụ:

Sau đây là ví dụ cho thấy cách tạo một số thẻ bằng các nút điều hướng sẽ chuyển đổi giữa các thẻ đó. Bạn có thể thêm các thẻ này vào ngăn xếp theo ngữ cảnh hoặc không theo ngữ cảnh bằng cách đẩy thẻ do createNavigationCard() trả về vào hoặc bên ngoài một ngữ cảnh cụ thể.

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