A maioria dos complementos baseados em cards é criada usando vários cards que representam "páginas" diferentes 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 são processadas empurrando e destacando cards de e para uma única pilha de cards, com o cartão superior da pilha exibido pelo Gmail.
Os complementos do Google Workspace introduzem
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 de cards interna
para cada um deles. Quando um complemento é aberto
em um host, o homepageTrigger
correspondente é acionado para criar o primeiro
card da página inicial na pilha (o card azul escuro "Página inicial" no diagrama abaixo).
Se um homepageTrigger
não for 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 "cartões enviados" azuis no diagrama) à medida que o usuário navega pelo complemento. A interface do complemento mostra o card superior na pilha. Portanto, enviar novos cards para a pilha muda a exibição, e remover 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 do gatilho
cria o card contextual, mas a exibição da interface é atualizada com base no
DisplayStyle
do novo card:
- Se
DisplayStyle
forREPLACE
(o padrão), o card de contexto (o card "contextual" laranja escuro no diagrama) substituirá o card exibido no momento. Isso inicia uma nova pilha de cards contextuais na parte de cima da pilha de cards não contextuais, que é o cartão raiz da pilha contextual. - Se
DisplayStyle
forPEEK
, a interface vai criar um cabeçalho que aparece na parte de baixo da barra lateral do complemento, sobrepondo o card atual. O cabeçalho exibido mostra o título do novo card e fornece controles de botão ao usuário que permitem que ele decida se quer ver o novo card ou não. Se ele clicar no botão Ver, o cartão substituirá o cartão atual (como descrito acima porREPLACE
).
É possível criar outros cartões contextuais e enviá-los para a pilha (os "cartões enviados" amarelos no diagrama). Atualizar a pilha de cards muda a interface do complemento para mostrar o card na parte de cima. Se o usuário sair de um contexto, os cards de contexto na pilha serão removidos, e a tela será atualizada para a página inicial ou o card não contextual mais acima.
Se o usuário entrar em um contexto em que seu complemento não tenha definido um acionador contextual, nenhum cartão novo será criado, e o cartão atual vai continuar sendo exibido.
As ações Navigation
descritas abaixo só funcionam em cards do mesmo contexto. Por exemplo,
popToRoot()
de um card de contexto 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 que o usuário navegue 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 de cards. A classe Navigation
fornece funções para enviar e retirar cards das pilhas. Para criar
uma navegação de card eficaz, configure seus
widgets para usar
ações de navegação. Você pode enviar ou destacar vários cards simultaneamente, mas não é possível remover o card inicial da página inicial que é enviado para a pilha quando o complemento é iniciado.
Para navegar para um novo card em resposta a uma interação do usuário com um widget, siga estas etapas:
- Crie um objeto
Action
e associe-o a uma função de callback definida por você. - Chame a função do gerenciador de widgets
apropriada do widget para definir o
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 do 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
criado.
- Crie um objeto
Ao criar controles de navegação, você usa as seguintes
funções do objeto Navigation
:
Função | Descrição |
---|---|
Navigation.pushCard(Card) |
Envia um card para a pilha atual. Isso requer criar o cartão completamente primeiro. |
Navigation.popCard() |
Remove um card do topo da pilha. É equivalente a clicar na seta para voltar na linha do cabeçalho do complemento. Isso não remove cartões raiz. |
Navigation.popToRoot() |
Remove todos os cards da pilha, exceto o cartão raiz. Essencialmente, redefine a pilha de cards. |
Navigation.popToNamedCard(String) |
Retira cards da pilha até que eles cheguem a um card com o nome informado ou o card raiz da pilha. É possível atribuir nomes aos cards usando a função CardBuilder.setName(String) . |
Navigation.updateCard(Card) |
Faz uma substituição no local do cartão atual, atualizando a exibição na interface. |
Prática recomendada de navegação
Se uma interação ou um evento do usuário 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
na nova renderização de cards em um contexto diferente, use
ActionResponseBuilder.setStateChanged()
para forçar a reexecução do complemento nesses contextos.
Confira 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 que o usuário
realize outra ação (por exemplo, clicar no título de um item para ver mais detalhes ou
pressionar um botão para criar um novo evento da 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 um evento atualizar o estado em um card anterior (por exemplo,
atualizar o título de um item com a visualização de detalhes), use algo como
popCard()
,popCard()
pushCard(previous)
epushCard(current)
para atualizar o card anterior e o atual.
Atualizando cards
Com os complementos do Google Workspace, os usuários podem atualizar seu card executando novamente a função de acionador do Apps Script registrada no seu manifesto. Os usuários acionam essa atualização com um item de menu de complemento:
Essa ação é adicionada automaticamente aos cards gerados pelas funções de acionamento homepageTrigger
ou
contextualTrigger
, conforme especificado no arquivo de manifesto do seu complemento (as "raízes" das pilhas de cards contextuais e não contextuais).
Como retornar vários cartões
As funções de página inicial ou de gatilho contextual são usadas para criar e retornar
um único objeto
Card
ou uma matriz de objetos
Card
exibidos pela
interface do aplicativo.
Se houver apenas um cartão, ele será adicionado à pilha não contextual ou contextual como o cartão raiz, e a interface do aplicativo host o exibirá.
Se a matriz retornada incluir mais de um objeto
Card
criado, o aplicativo host exibirá um novo cartão, com uma
lista do cabeçalho de cada cartão. Quando o usuário clica em qualquer um desses cabeçalhos, a interface
exibe o card correspondente.
Quando o usuário seleciona um cartão na 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çalho do cartão.Essa organização de card "plano" pode funcionar bem se seu complemento não precisar de transições entre os cards criados. No entanto, na maioria dos casos, é uma prática recomendada definir diretamente as transições de card e fazer com que a página inicial e as funções de acionador 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 enviando 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();
}