A maioria dos complementos baseados em cards é criada usando vários cards que representam diferentes "páginas" da interface do complemento. Para ter uma experiência do usuário eficaz, use a navegação simples e natural entre os cards no seu complemento.
Originalmente, nos complementos do Gmail, as transições entre diferentes cards da interface eram gerenciadas empurrando e abrindo cards de e para uma única pilha de cards, com o card superior da pilha exibido pelo Gmail.
Os complementos do Google Workspace apresentam
páginas iniciais e
cards não contextuais. Para acomodar cards contextuais e não contextuais,
os complementos do Google Workspace têm uma pilha interna de cards
para cada um. Quando um complemento é aberto
em um host, o homepageTrigger
correspondente é acionado para criar o primeiro
card da página inicial na pilha (o card "página inicial" azul escuro no diagrama abaixo).
Se um homepageTrigger
não for definido, um card padrão será criado, exibido
e inserido na pilha não contextual. Esse primeiro card é raiz.
Seu complemento pode criar outros cards não contextuais e enviá-los para a pilha (os "cards enviados" azuis no diagrama) à medida que o usuário navega pelo complemento. A interface do complemento mostra o card de cima na pilha. Portanto, ao adicionar novos cards à pilha, a tela muda, e ao remover cards da pilha, a tela volta a mostrar os cards anteriores.
Se o complemento tiver um gatilho contextual definido, ele será acionado quando o usuário entrar nesse contexto. A função de gatilho
cria o card contextual, mas a exibição da interface é atualizada com base no
DisplayStyle
do novo card:
- Se o
DisplayStyle
forREPLACE
(o padrão), o cartão contextual (o cartão laranja escuro "contextual" no diagrama) vai substituir o que está sendo mostrado. Isso inicia uma nova pilha de cards contextuais sobre a pilha de cards não contextual, e esse card contextual é o card raiz da pilha contextual. - Se o
DisplayStyle
forPEEK
, a interface vai criar um cabeçalho de visualização que aparece na parte de baixo da barra lateral do complemento, sobrepondo o card atual. O cabeçalho de visualização mostra o título do novo card e fornece os controles de botão do usuário que permitem decidir se o novo card será exibido ou não. Se o usuário clicar no botão View, o card vai substituir o atual (conforme descrito acima comREPLACE
).
Você pode criar outros cards contextuais e colocá-los na pilha (os "cards empurrados" amarelos no diagrama). Atualizar a pilha de cards muda a interface do complemento para mostrar o card mais importante. Se o usuário sair de um contexto, os cards contextuais na pilha serão removidos, e a exibição será atualizada para o card não contextual ou a página inicial mais alta.
Se o usuário inserir um contexto para o qual seu complemento não define um gatilho contextual, nenhum novo cartão será criado, e o cartão atual vai continuar sendo mostrado.
As ações Navigation
descritas abaixo só atuam em cards do mesmo contexto. Por exemplo,
popToRoot()
em um card contextual só aparece todos os outros cards contextuais e
não afeta os cards da página inicial.
Por outro lado, o botão
está sempre disponível para o usuário navegar dos cards contextuais para os não contextuais.Métodos de navegação
É possível criar transições entre cards adicionando ou removendo cards das
pilhas. A classe Navigation
oferece funções para inserir e remover cards das pilhas. Para criar
uma navegação de cards eficaz, configure seus
widgets para usar
ações de navegação. É possível enviar ou abrir
vários cards ao mesmo tempo, mas não é possível remover o card inicial da página inicial
que é enviado primeiro para a pilha quando o complemento é iniciado.
Para navegar até um novo card em resposta a uma interação do usuário com um widget, siga estas etapas:
- Crie um objeto
Action
e o associe a uma função de callback definida por você. - Chame a função de gerenciador de widget
adequada para definir o
Action
no widget. - Implemente a função de callback que conduz a navegação. Essa função
recebe um objeto de evento de ação
como argumento e precisa fazer o seguinte:
- Crie um objeto
Navigation
para definir a mudança de cartão. Um único objetoNavigation
pode conter várias etapas de navegação, que são realizadas na ordem em que são adicionadas ao objeto. - Crie um objeto
ActionResponse
usando a classeActionResponseBuilder
e o objetoNavigation
. - Retorne o
ActionResponse
integrado.
- Crie um objeto
Ao criar controles de navegação, você usa as seguintes
funções de objeto Navigation
:
Função | Descrição |
---|---|
Navigation.pushCard(Card) |
Insere um card na pilha atual. Para isso, é necessário criar o cartão completamente primeiro. |
Navigation.popCard() |
Remove um card da parte de cima da pilha. Equivalente a clicar na seta para voltar na linha de cabeçalho do complemento. Isso não remove os cards raiz. |
Navigation.popToRoot() |
Remove todos os cards da pilha, exceto o card raiz. Essencialmente, ele redefine a pilha de cards. |
Navigation.popToNamedCard(String) |
Remove cards da pilha até encontrar um card com o nome especificado ou o card raiz da pilha. É possível atribuir nomes a cards usando a função CardBuilder.setName(String) . |
Navigation.updateCard(Card) |
Faz a substituição no local do card atual, atualizando a exibição dele na IU. |
Prática recomendada de navegação
Se uma interação ou evento do usuário resultar na renderização de cards no mesmo
contexto, use os métodos
Navigation.pushCard()
,
Navigation.popCard()
e Navigation.updateCard()
para substituir os cards atuais. Se uma interação ou um evento do usuário precisar
resultar na renderização de cards em um contexto diferente, use
ActionResponseBuilder.setStateChanged()
para forçar a reexecução do seu complemento nesses contextos.
Confira abaixo alguns exemplos de navegação:
- Se uma interação ou um evento mudar o estado do card atual (por exemplo,
adicionar uma tarefa a uma lista de tarefas), use
updateCard()
. - Se uma interação ou um evento fornecer mais detalhes ou solicitar uma ação
adicional do usuário (por exemplo, clicar no título de um item para ver mais detalhes ou
pressionar um botão para criar um novo evento do Google Agenda), use
pushCard()
para mostrar a nova página e permitir que o usuário saia dela usando o botão "Voltar". - Se uma interação ou evento atualizar o estado em um card anterior (por exemplo,
atualizar o título de um item com a visualização detalhada), use algo como
popCard()
,popCard()
,pushCard(previous)
epushCard(current)
para atualizar o card anterior e o atual.
Atualizar cards
Os complementos do Google Workspace permitem que os usuários refresquem o card executando novamente a função de acionador do Apps Script registrada no manifesto. Os usuários ativam essa atualização usando um item de menu de complemento:
Essa ação é adicionada automaticamente aos cards gerados por funções de gatilho homepageTrigger
ou
contextualTrigger
, conforme especificado no arquivo de manifesto do complemento,
as "raízes" das pilhas de cards contextuais e não contextuais.
Como retornar vários cards
As funções de gatilho contextual ou da página inicial são usadas para criar e retornar
um único objeto
Card
ou uma matriz de
objetos Card
que a
interface do aplicativo mostra.
Se houver apenas um card, ele será adicionado à pilha não contextual ou contextual como o card raiz, e a interface do aplicativo host será mostrada.
Se a matriz retornada incluir mais de um objeto
Card
criado, o aplicativo host vai mostrar um novo card, que contém uma
lista de cada cabeçalho. Quando o usuário clica em qualquer um desses cabeçalhos, a interface
mostra o card correspondente.
Quando o usuário seleciona um card da lista, ele é enviado para a pilha atual e o aplicativo host é exibido. O botão
retorna o usuário à lista de cabeçalhos de cards.Essa disposição de cards "planos" pode funcionar bem se o complemento não precisar de nenhuma transição entre os cards criados. Na maioria dos casos, no entanto, é melhor definir diretamente as transições de cards e fazer com que a página inicial e as funções de gatilho contextual retornem um único objeto de card.
Exemplo
Confira um exemplo que mostra como criar vários cards com botões de navegação
que pulam entre eles. Esses cards podem ser adicionados à pilha
contextual ou não contextual ao enviar o card retornado
por createNavigationCard()
dentro ou fora de um contexto específico.
/**
* 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();
}