A maioria dos complementos baseados em cartões é criada usando vários cartões que representam diferentes "páginas" da interface complementar. Para que o usuário tenha uma experiência 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 IU são processadas com o envio e o envio de cards 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 cartões contextuais e não contextuais,
os complementos do Google Workspace têm uma pilha de cartões interna
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 "homepage" azul-escuro no diagrama abaixo).
Se um homepageTrigger
não estiver definido, um cartão padrão será criado, exibido
e enviado para a pilha não contextual. O primeiro é um cartão raiz.
Seu complemento pode criar outros cards não contextuais e enviá-los para a pilha (os "cards enviados" em azul no diagrama) conforme o usuário navega pelo complemento. A IU dos complementos exibe o cartão superior na pilha, portanto, o envio de novos cartões para a pilha altera a exibição, e remover os cards da pilha retorna a exibição para os cards anteriores.
Se o complemento tiver um
acionador contextual definido,
quando o usuário entrar nesse contexto, o acionador será disparado. A função de gatilho
cria o card contextual, mas a exibição da IU é atualizada com base no
DisplayStyle
do novo cartão:
- Se o
DisplayStyle
forREPLACE
(o padrão), o card de contexto (o cartão "contexto" laranja escuro no diagrama) vai substituir o card exibido. Isso inicia efetivamente uma nova pilha de cards contextuais sobre a pilha de cards não contextuais. Esse card é raiz da pilha de contexto. - Se o
DisplayStyle
forPEEK
, a IU vai criar um cabeçalho de exibição na parte inferior da barra lateral do complemento, sobrepondo o card atual. O cabeçalho da exibição mostra o título do novo cartão e fornece os controles do botão de usuário que permitem decidir se o novo card vai ser exibido ou não. Se ele clicar no botão Ver, o cartão substituirá o cartão atual (conforme descrito acima porREPLACE
).
É possível criar outros cards contextuais e enviá-los para a pilha (os "cards enviados" amarelos no diagrama). A atualização da pilha de cartões altera a IU do complemento para exibir o cartão mais próximo. Se o usuário sair de um contexto, os cards contextuais na pilha serão removidos e a exibição será atualizada no card ou na página inicial não contextual principal.
Se o usuário entrar em um contexto em que seu complemento não define um acionador contextual, nenhum cartão novo será criado e o cartão atual permanecerá exibido.
As ações Navigation
descritas abaixo atuam apenas em cards do mesmo contexto. Por exemplo,
popToRoot()
em um card contextual mostra apenas 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 cartões adicionando ou removendo cards das
pilhas de cartões. A classe Navigation
fornece funções para enviar e retirar cards das pilhas. Para criar
uma navegação eficaz com cards, configure os
widgets para usar
ações de navegação. Você pode enviar ou abrir
vários cartões simultaneamente, mas não é possível remover o cartão inicial da página inicial
que é enviado pela primeira vez 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
apropriada para definir a
Action
nesse 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 no cartão. Um único objetoNavigation
pode conter várias etapas de navegação, que são conduzidas na ordem em que são adicionadas ao objeto. - Crie um objeto
ActionResponse
usando a classeActionResponseBuilder
e o objetoNavigation
. - Retorne o
ActionResponse
criado.
- Crie um objeto
Ao criar controles de navegação, use as seguintes
funções de objeto Navigation
:
Função | Descrição |
---|---|
Navigation.pushCard(Card) |
Envia um cartão para a pilha atual. Isso requer a criação completa do cartão. |
Navigation.popCard() |
Remove um cartão da parte de cima da pilha. Equivalente a clicar na seta para voltar na linha do cabeçalho do complemento. Isso não remove os cartões raiz. |
Navigation.popToRoot() |
Remove todos os cartões da pilha, exceto o cartão raiz. Basicamente, redefine essa pilha do cartão. |
Navigation.popToNamedCard(String) |
Destaca os cartões da pilha até atingirem um cartão com o nome informado ou o cartão raiz da pilha. É possível atribuir nomes a cards usando a função CardBuilder.setName(String) . |
Navigation.updateCard(Card) |
Faz uma substituição no lugar do cartão atual, atualizando a exibição dele na IU. |
Práticas recomendadas de navegação
Se uma interação do usuário ou um evento precisar resultar em uma nova 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 do usuário ou um evento resultar
em uma nova renderização de cards em um contexto diferente, use
ActionResponseBuilder.setStateChanged()
para forçar a nova execução do complemento nesses contextos.
Veja a seguir 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 ao usuário mais ações (por exemplo, clicar no título de um item para ver mais detalhes ou pressionar um botão para criar um novo evento do Agenda), use
pushCard()
para mostrar a nova página enquanto permite que o usuário saia da nova página usando o botão "Voltar". - Se uma interação ou um evento for atualizado no estado de um card anterior (por exemplo,
atualizando o título de um item com a visualização detalhada), use algo como
popCard()
,popCard()
,pushCard(previous)
epushCard(current)
para atualizar o cartão anterior e o atual.
Atualizando cards
Com os complementos do Google Workspace, os usuários podem atualizar seu cartão executando novamente a função de gatilho do Apps Script registrada no seu manifesto. Os usuários acionam essa atualização em um item de menu complementar:
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 cartões
As funções de acionador da página inicial ou do contexto são usadas para criar e retornar
um único objeto
Card
ou uma matriz de
objetos Card
que a
IU do aplicativo exibe.
Se houver apenas um cartão, ele vai ser adicionado à pilha não contextual ou contextual, como o cartão raiz e a IU do aplicativo host o exibe.
Se a matriz retornada incluir mais de um objeto
Card
criado, o aplicativo host exibirá um novo cartão, que contém uma
lista de cabeçalhos de cada cartão. Quando o usuário clica em qualquer um desses cabeçalhos, a IU
mostra o cartão correspondente.
Quando o usuário seleciona um cartão da lista, esse cartão é enviado para a pilha atual, e o aplicativo host o exibe. O botão
retorna o usuário à lista de cabeçalhos do cartão.Essa organização de cards "simples" pode funcionar bem se o complemento não precisar de transições entre cartões criados por você. Na maioria dos casos, no entanto, é uma prática recomendada definir diretamente as transições de cartão e fazer com que a página inicial e as funções de acionadores contextuais retornem um único objeto de cartão.
Exemplo
Veja 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 cartão 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();
}