Design system com Jetpack Compose: Criando componentes

Pablo Baldez
Android Dev BR
Published in
5 min readMar 12, 2021

Talvez esse seja o primeiro post de uma série sobre o design system adotado pela Warren e como podemos usar a promissora ferramenta de desenvolvimento de UI nativo para Android, Jetpack Compose. Vou tentar trazer algumas dicas, boas práticas e cuidados que precisam ser levados em consideração na hora de usar essa nova ferramenta.

Pra quem não sabe o que é Design System, aqui vai uma imagem que explica bem sua definição (até pq essa não é a proposta original do post hehe)

Existem muitos exemplos de DS por aí! O Material Design é provavelmente o mais próximo de nós, desenvolvedores Android. Nele existem uma série de regras, boas práticas e recomendações e, obviamente, uma lista de componentes, como Button, Toolbar, Checkbox…

Estamos trabalhando em ferramentas para ter o nosso próprio Design System dentro de casa, procurando ganhar mais produtividade, reuso de código e uniformidade entre todas telas do app. Para isso, um dos primeiros passos foi implementar nosso set de componentes visuais, começando pelo component mais usado entre todos, que chamamos de Row.

Row: componente mais usado nas telas do projeto

Como se pode ver, esse componente contém uma muitas variações com pequenas diferenças cada, e deve permitir combinações como:

  • Ícones com tamanhos diferentes alinhados esquerda
  • Ao invés de ícone, um gráfico circular a esquerda
  • Textos alinhados horizontalmente e verticalmente
  • Tipografias diferentes para os textos

E essa complexidade nos trouxe o primeiro questionamento.

Quantas funções @Composables serão necessárias?

O ideal seria implementar o mínimo possível de funções para a utilização da Row, pois uma de nossas premissas para o Design System é implementar uma ferramenta enxuta e objetiva, e o que vai nos ajudar nisso é também a primeira dica que deixo aqui: use slots.

Slots é uma técnica básica de Compose que consiste em funções Composables que recebem outras funções Composables por parâmetro. A maioria das funções de componentes nativos funcionam assim, como o Button.

O caso da nossa Row não é diferente. Ao invés de implementar várias funções com parâmetros diferentes, optamos por implementar apenas 2 funções, responsáveis por definir espaçamentos e a distribuição interna dos Composables.

Como resultado final temos:

  • FoundationRow: Tem esse nome por ser a Row fundamental do projeto. É apenas um retângulo que aplica espaçamentos laterais
  • RegularRow: Função que usa a FoundationRow e distribui 4 slots horizontais.
Exemplo visual da implementação de Rows (Foundation e Regular, respectivamente)

Mas e o textos verticais?

Como você deve ter percebido, dividimos a Row em no máximo 4 slots. Mas e as rows cujo os textos estão alinhados verticalmente?

Bom, uma boa prática durante o uso de Composable funtions é modularizar seus componentes em componentes menores, de forma que seja possível reutilizá-los da melhor forma possível. Ao invés de implementarmos mais slots na row, entendemos que a responsabilidade de organizar os textos de forma vertical não é dela, e sim de componente, denominado TwoLine.

Agora, fazendo a combinação dos Composables, é possível implementar variações de Row com facilidade

E o resultado obtido

Use Providers. Use muito Providers!

Nós estamos quase perto do fim, entretanto alguns pontos precisam ser melhorados. Na especificação de Row do nosso Design system, os textos abaixo tem cores e tamanhos diferentes dos de cima. Além disso, a dupla de textos à esquerda, tem o alinhamento dos textos a esquerda, enquanto a dupla da direita tem o alinhamento dos textos a direita.

Rows com cada TwoLine usando alinhamentos diferentes

Poderíamos pensar em parâmetros relacionados a tipografia e alinhamentos no TwoLine certo? Na verdade, nem tanto. Existe uma opção melhor: Providers!

Providers são uma forma de configurar nodos de Composables, onde uma função Composable pai determina que todos os composables dentro de um respectivo nodo utilizarão uma configuração específica.

Podemos fazer algumas alterações no nosso TwoLine para garantir que tudo o que for adicionado no nodo primary terá um TextStyle, e o que for adicionado no nodo secondary terá outro

Mas e os alinhamentos? Bom, se toda vez que formos usar a Row queremos que o texto nas colunas da direita fiquem alinhados à direita, podemos seguir a mesma linha de raciocínio e aplicar providers para isso.

Nesse caso, existe um provider em particular que pode nos ajudar aqui, que inverte o alinhamento natural dos layouts, fazendo com que os nodos filhos sejam adicionados da direita pra esquerda. Para isso é preciso fazer uma pequena alteração na nossa RegularRow

Agora que utilizamos o AmbientLayoutDirection o conteúdo adicionado no slot detail ficará alinhado a direita. Tudo isso sem a adição de parâmetros e configurações repetidas ao usar o componente. Muito fácil!

Pronto!

Com esses últimos ajustes finalizamos a Row do nosso Design System. Um componente simples em sua essência, mas que por permitir tanta flexibilidade e customização, esconde consigo bastante armadilhas.

Por sorte a ferramenta Compose nos oferece muitos recursos para conseguir entregar UI simples e objetiva, como sempre deveria ser. Usando e abusando de conceitos como Slots e Providers, conseguimos chegar em uma solução final elegante.

Em breve vou voltar a escrever mais sobre design system e boas práticas de uso do Compose, então fique atento ao blog para estar por dentro das novidades. Também deixe seu comentário com sugestões e críticas à solução proposta. Por ser uma ferramenta nova, esse tipo de debate acaba sendo muito válido!

Agradeço sua atenção até aqui,

Obrigado

--

--

Pablo Baldez
Android Dev BR

Desenvolvedor android a muito tempo. Interessado por aprender sobre tudo que posso desde sempre.