O Jetpack Compose é uma ferramenta bastante poderosa para criar telas nativas no Android.
Embora a ideia da ferramenta seja facilitar a implementação de telas, se não compreendermos a finalidade de cada componente, não será uma tarefa fácil!
Considerando esses detalhes, vamos entender como devemos pensar no momento que criamos uma tela.
Amostra de implementação
Como demonstração, vamos utilizar a seguinte tela:
Agora que conhecemos a tela, precisamos compreender a lógica de analise antes de começar a implementação.
Identificando os elementos visuais
Como primeiro passo, podemos começar a analise identificando os elementos visuais. De uma forma genérica, temos:
- imagem de capa
- texto de título
- texto de subtítulo
- ícone de favorito
- botão de leitura
Analisando o layout da tela
Então, precisamos analisar o layout geral. Observe que todos os elementos estão organizados em coluna, sendo que o ícone e botão, estão em linha!
Com apenas essa analise, podemos implementar o primeiro código da tela com composable de layout:
Column {
AsyncImage(
"https://picsum.photos/1920/1080",
contentDescription = "Imagem de capa"
)
Text(text = "Título")
Text(text = "Subtitulo")
Row {
Icon(
Icons.Outlined.FavoriteBorder,
contentDescription = "ícone de favorito"
)
Button(onClick = { /*TODO*/ }) {
Text(text = "Ler agora")
}
}
}
Embora o design não esteja fiel a amostra, já temos tudo que precisamos para seguir com o próximo passo, personalizar os componentes da tela.
Fazendo uma analogia ao front-end na web, basicamente, adicionamos o HTML para estruturar a página!
Personalizando a tela com o Modifier
Assim como há os composables para estruturar a tela, temos o Modifier como entidade responsável em personalizar, dar comportamentos e reagir a eventos dos composables. Sendo assim, vamos utilizá-lo para modificar os composables
Seguindo a analogia com front-end, o
Modifierseria um CSS do Jetpack Compose.
Ajustando o container principal
Podemos começar a personalização por qualquer componente, mas, geralmente tendo seguir uma estratégia, começar pelo componente mais externo até o mais interno, portanto, vamos começar com o Column mais externo:
Column(
Modifier
.padding(8.dp)
.fillMaxWidth()
.border(
0.5.dp,
Color.Gray.copy(alpha = 0.5f),
RoundedCornerShape(20.dp)
)
) {
...
}
Todo composable recebe como primeiro parâmetro opcional um
Modifier, pois existe oModifierpadrão. Para mais detalhes, você pode verificar nesta thread sobre modificadores..
Note que agora já temos um destaque ao container que representa o card, exibindo um espaçamento e bordas arredondadas.
Personalizando a imagem de capa
Por mais que o container do card foi ajustado corretamente, a imagem ainda apresenta o aspecto quadrado e ultrapassa as extremidades do container principal, para resolver isso, podemos aplicar o modificador na imagem também:
Column(
...
) {
AsyncImage(
"https://picsum.photos/1920/1080",
contentDescription = "Imagem de capa",
Modifier
.height(100.dp)
.clip(
RoundedCornerShape(
topStart = 20.dp,
topEnd = 20.dp
)
),
contentScale = ContentScale.Crop,
placeholder = ColorPainter(Color.Gray)
)
...
}
Note que além do modificador, utilizei alguns parâmetros próprios do AsyncImage:
-
contentScale: o container da imagem vai ter uma altura fixa, na escala padrão, ela fica distorcida ao tentar exibir todo conteúdo da imagem. Aplicando o corte com oContentScale.Crop, apresenta a imagem cortada no espaço disponível. -
placeholder: apresenta conteúdo no preview e durante o carregamento da imagem via internet, nesse caso, um fundo cinza
Agora que a imagem de capa foi ajustada, vamos para os textos.
Modificando os textos
Podemos modificar os textos da seguinte maneira:
Column(
...
) {
...
Text(
text = "Título",
Modifier.padding(
start = 16.dp,
top = 16.dp,
end = 16.dp,
bottom = 8.dp
),
fontSize = 24.sp
)
Text(
text = "Subtitulo",
Modifier.padding(
start = 16.dp,
end = 16.dp,
bottom = 16.dp
),
fontSize =
14.sp
)
...
}
}
Mesmo que os textos foram modificados como esperado, é válido notar que tivemos que aplicar diversos números para o espaçamento...
Em casos como esses, podemos utilizar composables de layout para simplificar a implementação, como por exemplo, envolver os Texts em coluna e modificar o espaçamento da coluna e ajustar o arranjo vertical:
Column(
...
) {
...
Column(
Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "Título",
fontSize = 24.sp
)
Text(
text = "Subtitulo",
fontSize = 14.sp
)
}
...
}
Tanto o
Rowcomo oColumn, possuem parâmetros extras para manipular os seus filhos, ou seja, os composables que são organizados por eles.
Com esse ajuste, temos o mesmo resultado de antes! Mais simples, concorda? Por fim, precisamos apenas ajustar a linha final.
Ajustando o ícone e botão em linha
O ajuste da linha é bastante similar ao que fizemos na coluna anterior:
Column(
...
) {
...
Row(
Modifier
.padding(16.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
Icons.Outlined.FavoriteBorder,
contentDescription = "ícone de favorito"
)
Button(onClick = { /*TODO*/ }) {
Text(text = "Ler agora")
}
}
}
A grande diferença fica na aplicação da largura com o fillMaxWidth() em conjunto do arranjo e alinhamento.
Essa técnica é utilizada para que seja possível aplicar o Arrangement.SpaceBetween que organiza os filhos nas extremidades, já o alinhamento, centraliza os filhos verticalmente.
Conclusão
Em um primeiro momento, a implementação de telas no Jetpack Compose pode parecer complexa, porém, vimos que podemos aplicar algumas técnicas para facilitar a escrita de código.
Considerando o que vimos, temos:
- identificação dos elementos visuais
- analise do layout
- aplicação de modificadores em cada componente
- ordem de modificação para facilitar
O que achou de criar telas no Jetpack Compose? Você já usa essas técnicas ou tem outros macetes para facilitar a implementação?






Top comments (1)
Parabéns pelo conteúdo de alta qualidade Felipe. Sucesso!