Os desenvolvedores podem personalizar o processo de geração de código fornecendo um mapeamento entre um pacote da IU e um componente de código existente em vez do código gerado. Isso é benéfico quando a implementação atual tem recursos que não podem ser obtidos pelo código gerado, como animação ou comportamento complexo (como um menu suspenso).
Os desenvolvedores especificam como mapear componentes usando um arquivo de mapeamento. Um arquivo de mapeamento informa ao gerador de código, no mínimo, como alcançar a função combinável de destino para que o código de cliente correto possa ser criado.
Confira um exemplo:
No Figma, um designer cria um componente Card que contém uma instância de um componente Play Bar, empacota os dois componentes e os envia a um desenvolvedor.
Quando o desenvolvedor importa os pacotes de interface do Figma, dois diretórios são
criados em ui-packages
: card
e play_bar
. Ao criar o projeto,
duas funções de composição são criadas: Card
e PlayBar
. Normalmente, como
Card contém uma instância de Play Bar no Figma, no código a função combinável Card
contém uma chamada para o elemento combinável PlayBar
.
No entanto, o designer e o desenvolvedor querem que o Card
use um elemento combinável o MyExistingPlaybar
, que tem uma funcionalidade difícil de
descrever no Figma. Portanto, o desenvolvedor adiciona um arquivo de mapeamento chamado play_bar.json
que mapeia o pacote de IU do play_bar
para MyExistingPlaybar
:
{
"target": "MyExistingPlaybar",
"package": "com.example.myApp"
}
Agora, quando o desenvolvedor cria o projeto, o Card
chama MyExistingPlaybar
,
em vez de PlayBar
. Observe que MyExistingPlaybar
precisa ter os mesmos
parâmetros que PlayBar
, embora possa haver algumas diferenças, conforme descrito
em Diretivas adicionais abaixo.
Arquivo de mapeamento
Nos projetos do Android Studio, os arquivos de mapeamento são adicionados em
ui-package-resources/mappings
ao lado da pasta ui-packages
. O Relay procura
arquivos de mapeamento durante a criação.
Gerar um arquivo de mapeamento
O Relay pode gerar um arquivo de mapeamento para qualquer pacote de IU importado. Siga estas etapas:
Clique com o botão direito do mouse na pasta do pacote ou em qualquer arquivo dentro da pasta
ui-package
de destino. Selecione Gerar arquivo de mapeamento.Configure as seguintes opções na caixa de diálogo:
Local do arquivo:define o local do arquivo de mapeamento gerado.
Elemento combinável de destino:define o elemento combinável personalizado que é usado em vez do elemento combinável gerado. Você tem a opção de usar um combinável existente ou criar um novo na caixa de diálogo. A criação de um elemento combinável cria um elemento combinável com os mesmos parâmetros definidos no pacote de interface.
- Arquivo gerado:define as opções
generateImplementation
egeneratePreview
no arquivo de mapeamento. Consulte Mapeamento de conteúdo de arquivos abaixo para mais detalhes.
Clique em Gerar arquivo de mapeamento. Um novo arquivo de mapeamento é criado na pasta
ui-package-resources/mapping
com as configurações especificadas.
Também é possível abrir a caixa de diálogo Generate mapping file na interface do módulo de pacote do Relay seguindo estas etapas:
Clique em qualquer arquivo de um pacote de interface na pasta
ui-package
de destino.Se a janela da ferramenta de retransmissão não abrir automaticamente, clique no ícone de retransmissão para abrir a janela.
Clique no botão Generate mapping file em Package Options.
Nome do arquivo de mapeamento
O nome de um determinado arquivo de mapeamento precisa corresponder ao nome da pasta do pacote de IU
para o componente substituído. Portanto, o play_bar.json
mapeia o pacote da IU na
pasta ui-packages/mappings
para um componente de código.
Mapear o conteúdo do arquivo
O arquivo de mapeamento contém as seguintes propriedades:
target:obrigatório. O nome da função combinável personalizada. Por padrão, esse é o nome da função criada pelo código gerado.
"target" : "CustomComposableName"
package: (obrigatório) nome do pacote em que o elemento combinável personalizado está inserido. Por padrão, é o pacote da função criada pelo código gerado.
"package" : "com.example.podcastapp.ui.components"
generateImplementation: (opcional) verdadeiro ou falso. Se verdadeiro, uma implementação desse pacote de interface ainda será criada no arquivo de código gerado. Se for "false", a implementação não será criada. Por padrão, esse valor é verdadeiro.
"generateImplementation" : true
generatePreviews: (opcional) verdadeiro ou falso. Se verdadeiro, uma visualização do componente personalizado mapeado é criada no arquivo de código gerado. Se for falso, nenhuma visualização será criada. Por padrão, esse valor é verdadeiro.
"generatePreviews" : true
Variantes mapeadas
Se um componente do Figma tiver variantes, o elemento combinável gerado vai ter parâmetros de tipo enumerado que codificam a variante. Isso foi descrito no tutorial Como processar variantes de design. Se você quiser mapear um componente do Figma com variantes para um código existente, ele precisa ser mapeado para um elemento combinável que use os mesmos parâmetros que o elemento gerado. Por exemplo, para um componente do Figma chamado Chip com uma variante que tem a propriedade ChipType, a assinatura do elemento combinável gerada pelo Chip vai ficar assim:
@Composable
fun Chip(
modifier: Modifier = Modifier,
chipType: ChipType = ChipType.Red,
chipText: String
) { ... }
Se você quiser que o componente do Chip do Figma seja mapeado para um elemento combinável MyChip
existente, a assinatura de MyChip
vai precisar ter a mesma assinatura do
elemento combinável gerado (supondo que nenhuma diretiva adicional seja especificada).
Conceitualmente, isso sugere que o componente de código existente é capaz de
ter as mesmas variantes de design que o componente do Figma.
Outras diretivas
Por exemplo, se a função combinável que você quer segmentar tiver a seguinte assinatura:
@Composable
fun MyChip(
modifier: Modifier = Modifier,
chipType: ChipType = ChipType.Red,
description: String // instead of chipText
) { ... }
É possível adicionar um bloco fieldMappings
ao arquivo de mapeamento que afeta o mapeamento dos parâmetros. Nesse caso, ele contém um mapeamento do parâmetro chipText
no Chip
para o parâmetro description
em MyChip
.
{
"target": "MyChip",
"package": "com.example.myApp",
"fieldMappings": [
{
"type": "parameter",
"source": "chipText",
"target": "description"
}
]
}
Os tipos para o bloco fieldMappings
incluem:
parameter
: mapeia um campo do pacote de interface para um parâmetro de código.source
: nome do parâmetro conforme especificado no pacote da interface.target
: nome do parâmetro conforme especificado no componente do código de destino.
lambda
: mapeia um campo do pacote da IU para uma lambda de conteúdo.source
: nome do parâmetro conforme especificado no pacote da interface.target
: nome do parâmetro conforme especificado no componente do código de destino.
modifier
: mapeia um campo de pacote da interface para um método modificador.source
: nome do parâmetro conforme especificado no pacote da interface.method
: método no objeto modificador que precisa ser invocado no código gerado.parameter
: nome do parâmetro no método modificador especificado.library
: o nome do pacote qualificado a ser importado para acessar o método modificador.scope
: um dos dois valores para indicar o escopo do modificador:any
: o modificador pode ser usado em qualquer escopo de receptor.relay
: o modificador precisa ser usado no escopo do receptor do objetoRelayContainer
do Relay.