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
Modifier
seria 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 oModifier
padrã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 Text
s 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
Row
como 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!