Lição 1: funções que podem ser compostas
O Jetpack Compose foi criado com base em funções que podem ser compostas. Essas funções permitem que você defina a IU do app programaticamente, descrevendo as dependências de dados e de formas dela em vez de se concentrar no processo de construção da IU. Para criar uma função que pode ser composta, basta adicionar a anotação @Composable
ao nome da função.

Adicionar um elemento de texto
Para começar, siga as Instruções de configuração
do Jetpack Compose e crie um app usando o modelo Atividade vazia
do Compose. O modelo padrão já contém alguns elementos do Compose, mas vamos criá-lo passo a passo. Primeiro, exclua as funções "Saudação" e "Visualização padrão" e remova o bloco setContent
de MainActivity
, deixando a atividade em branco. Compile e execute seu app em branco.
Agora, adicione um elemento de texto à sua atividade em branco.
Para fazer isso, defina um bloco de conteúdo e chame a função Text()
.
O bloco setContent define o layout da atividade. Em vez de definir o conteúdo do layout com um arquivo XML, chamamos funções que podem ser compostas. O Jetpack Compose usa um plug-in personalizado do compilador Kotlin para transformar essas funções que podem ser compostas nos elementos de IU do app. Por exemplo, a função Text()
é definida pela biblioteca de IU do Compose. Chame essa função para declarar um elemento de texto no app.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text("Hello world!") } } }

Definir uma função que pode ser composta
As funções que podem ser compostas só podem ser chamadas de dentro do escopo de outras funções desse tipo. Para tornar uma função composta, adicione a anotação @Composable
. Para testar isso, defina uma função Greeting()
que recebe um nome e usa esse nome para configurar o elemento de texto.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Greeting("Android") } } } @Composable fun Greeting(name: String) { Text (text = "Hello $name!") }

Visualizar a função no Android Studio
O build canário atual do Android Studio
permite visualizar
suas funções que podem ser compostas no ambiente de desenvolvimento integrado, em vez de fazer o download do
app para um dispositivo ou emulador Android. A principal restrição é que a função composta não pode assumir nenhum parâmetro. Por isso, não é possível visualizar a função Greeting()
diretamente. Em vez disso, crie uma segunda função chamada PreviewGreeting()
, que chama Greeting()
com um parâmetro adequado.
Adicione a anotação @Preview
antes de @Composable
.
@Composable fun Greeting(name: String) { Text (text = "Hello $name!") } @Preview @Composable fun PreviewGreeting() { Greeting("Android") }

Recrie o projeto. O app em si não muda, porque a nova função previewGreeting()
não é chamada em nenhum lugar, mas o Android Studio adiciona uma janela de visualização. Essa janela mostra uma visualização dos elementos da IU criados pela função que pode ser composta marcada com a anotação @Preview
. Para atualizar as visualizações a qualquer momento, clique no botão Atualizar na parte superior da janela de visualização.

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text("Hello world!") } } }

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Greeting("Android") } } } @Composable fun Greeting(name: String) { Text (text = "Hello $name!") }

@Composable fun Greeting(name: String) { Text (text = "Hello $name!") } @Preview @Composable fun PreviewGreeting() { Greeting("Android") }


Lição 2: layouts
Os elementos da IU são hierárquicos, com elementos contidos em outros. No Compose, você cria uma hierarquia de IU chamando funções que podem ser compostas a partir de outras funções desse tipo.

Começar com texto
Volte para a atividade e substitua a função Greeting()
por uma nova função NewsStory()
. No restante do tutorial, você modificará a função NewsStory()
e não mexerá mais no código Activity
.
É uma prática recomendada criar funções de visualização separadas que não sejam chamadas pelo app. Ter funções de visualização dedicadas melhora o desempenho e também facilita a configuração de várias visualizações posteriormente. Por isso, crie uma função de visualização padrão que só chame a função NewsStory()
. À medida que você modifica NewsStory()
seguindo este tutorial, a visualização apresenta as mudanças.
Esse código cria três elementos de texto dentro da visualização do conteúdo. No entanto, como não fornecemos nenhuma informação sobre como organizá-los, os elementos de texto são desenhados uns sobre os outros, o que torna o texto ilegível.
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { NewsStory() } } } @Composable fun NewsStory() { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } @Preview @Composable fun DefaultPreview() { NewsStory() }

Como usar uma coluna
A função Column
permite empilhar elementos verticalmente. Adicione Column
à função NewsStory()
.
As configurações padrão empilham todos os filhos diretamente, um após o outro, sem espaçamento. A coluna é posicionada no canto superior esquerdo da visualização do conteúdo.
@Composable fun NewsStory() { Column { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

Adicionar configurações de estilo à coluna
Ao transmitir parâmetros para a chamada de Column
, é possível configurar o tamanho e a posição da coluna e de que maneira os filhos dela são organizados.
A configuração tem o seguinte significado:
modifier
: permite que você configure o layout. Nesse caso, aplique um modificadorModifier.padding
, que insere a coluna da visualização circundante.
@Composable fun NewsStory() { Column( modifier = Modifier.padding(16.dp) ) { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

Adicionar uma imagem
Queremos adicionar um gráfico acima do texto. Use o
Gerenciador de recursos para adicionar essa imagem
a recursos desenháveis do app, com o nome
header
.
Agora, modifique a função NewsStory()
.
Você adicionará uma chamada a Image()
para colocar o gráfico no
Column
. Esses elementos que podem ser compostos são disponibilizados no pacote "foundation", que você
talvez precise adicionar. Consulte as instruções de configuração do
Jetpack Compose.
A proporção da imagem ficará incorreta, mas isso não é um problema. Você corrigirá isso na
próxima etapa.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { Image(image) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

O gráfico é adicionado ao layout, mas ainda não foi dimensionado adequadamente.
Para definir o estilo do gráfico, transmita um Modifier
de tamanho para a chamada de
Image()
.
preferredHeight(180.dp)
: especifica a altura da imagem.fillMaxWidth()
: especifica que a imagem precisa ser larga o suficiente para preencher o layout ao qual pertence.
Você também precisa transmitir um parâmetro contentScale
para Image()
:
contentScale = ContentScale.Crop
: especifica que o gráfico precisa preencher a largura da coluna e ser recortado, se necessário, na altura apropriada.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

Adicione um Spacer
para separar o elemento gráfico dos títulos.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { NewsStory() } } } @Composable fun NewsStory() { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } @Preview @Composable fun DefaultPreview() { NewsStory() }

@Composable fun NewsStory() { Column { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

@Composable fun NewsStory() { Column( modifier = Modifier.padding(16.dp) ) { Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { Image(image) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

Lição 3: Material Design
O Compose foi criado para oferecer compatibilidade com os princípios do Material Design. Muitos dos elementos de IU implementam o Material Design por padrão. Nesta lição, você estilizará seu app com widgets do Material Design.

Aplicar uma forma
Um dos princípios do sistema do Material Design é Shape
. Use a função clip()
para arredondar os cantos da imagem.
Shape
é invisível, mas como o elemento gráfico é cortado para caber em Shape
, agora ele tem cantos levemente arredondados.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

Estilizar o texto
O Compose facilita o uso dos princípios do Material Design. Aplique MaterialTheme
aos componentes que você criou.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } } }

As mudanças são sutis, mas o texto agora usa o estilo de texto padrão de MaterialTheme
. Em seguida, aplique estilos de parágrafo específicos a cada elemento do texto.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove", style = typography.h6) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

Nesse caso, o título do artigo era curto. No entanto, pode ser que um artigo tenha um título longo, e não queremos que isso estrague a aparência do app. Tente mudar o primeiro elemento do texto.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text( "A day wandering through the sandhills " + "in Shark Fin Cove, and a few of the " + "sights I saw", style = typography.h6) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

Configure o elemento de texto para definir um comprimento máximo de duas linhas. A configuração não terá efeito se o texto for curto o suficiente para caber nesse limite, mas o texto exibido será truncado automaticamente se for muito longo.
@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text( "A day wandering through the sandhills " + "in Shark Fin Cove, and a few of the " + "sights I saw", style = typography.h6, maxLines = 2, overflow = TextOverflow.Ellipsis) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove") Text("Davenport, California") Text("December 2018") } } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text("A day in Shark Fin Cove", style = typography.h6) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text( "A day wandering through the sandhills " + "in Shark Fin Cove, and a few of the " + "sights I saw", style = typography.h6) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

@Composable fun NewsStory() { val image = imageResource(R.drawable.header) MaterialTheme { val typography = MaterialTheme.typography Column( modifier = Modifier.padding(16.dp) ) { val imageModifier = Modifier .preferredHeight(180.dp) .fillMaxWidth() .clip(shape = RoundedCornerShape(4.dp)) Image(image, modifier = imageModifier, contentScale = ContentScale.Crop) Spacer(Modifier.preferredHeight(16.dp)) Text( "A day wandering through the sandhills " + "in Shark Fin Cove, and a few of the " + "sights I saw", style = typography.h6, maxLines = 2, overflow = TextOverflow.Ellipsis) Text("Davenport, California", style = typography.body2) Text("December 2018", style = typography.body2) } } }

Tudo pronto
Bom trabalho! Você aprendeu as noções básicas do Compose.
Conteúdo abordado:
- Como definir funções que podem ser compostas
- Como usar e estilizar colunas para melhorar o layout
- Como estilizar seu app com os princípios do Material Design
Se você quiser se aprofundar em algumas dessas etapas, conheça os recursos abaixo.
Continue seu aprendizado
Experiência de aprendizado selecionado
Confira nosso caminho de codelabs e vídeos selecionados que ajudarão você a aprender como usar e dominar o Jetpack Compose.
Guias e outras documentações
Analise os documentos para saber mais sobre as APIs Jetpack Compose mencionadas neste tutorial.
Exemplos do Compose
Inspire-se com estes apps de amostra que demonstram como usar os recursos avançados do Compose.