1. Antes de começar
Desde o início, o Jetpack Compose foi criado com interoperabilidade de visualização, o que significa que ele e o sistema de visualização podem compartilhar recursos e trabalhar lado a lado para mostrar a interface. Essa funcionalidade permite adicionar o Compose ao seu app já existente baseado em visualização. Isso significa que o Compose e as visualizações podem coexistir na base de código até que todo o app esteja totalmente no Compose.
Neste codelab, você vai mudar o item de lista baseado em visualização no app Juice Tracker para usar o Compose. Você pode converter o restante das visualizações do Juice Tracker por conta própria, se quiser.
Se você tem um app que usa uma interface baseada em visualização, talvez não queira reprogramar toda a interface de uma vez. Este codelab ajuda a converter uma única visualização de uma interface baseada em visualização em um elemento do Compose.
Pré-requisitos
- Conhecer a interface baseada em visualização.
- Saber criar um app usando uma interface baseada em visualização.
- Ter experiência com a sintaxe do Kotlin, incluindo lambdas.
- Saber criar um app no Jetpack Compose.
O que você vai aprender
- Como adicionar o Compose a uma tela criada com visualizações do Android.
- Como visualizar um elemento combinável adicionado ao app baseado em visualização.
O que você vai criar
- Você vai converter um item de lista baseado em visualização para o Compose no app Juice Tracker.
2. Visão geral do app inicial
Este codelab usa o código de solução do app Juice Tracker mostrado em Criar um app Android com visualizações como o código inicial. O app inicial já salva dados usando a biblioteca de persistência Room. O usuário pode adicionar informações sobre sucos ao banco de dados do app, como nome, descrição, cor e nota.
Neste codelab, você vai converter o item de lista baseado em visualização para o Compose.
Fazer o download do código inicial para este codelab
Para começar, faça o download do código inicial:
Outra opção é clonar o repositório do GitHub:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-juice-tracker.git $ cd basic-android-kotlin-compose-training-juice-tracker $ git checkout views
Procure o código no repositório do GitHub do JuiceTracker
(link em inglês).
3. Adicionar a biblioteca do Jetpack Compose
Não se esqueça, Compose e Views podem existir juntos em uma determinada tela. Você pode ter alguns elementos da interface no Compose e outros no sistema de visualização. Por exemplo, você pode ter apenas a lista no Compose e o restante da tela no sistema de visualização.
Conclua as etapas a seguir para adicionar a biblioteca do Compose ao app Juice Tracker.
- Abra o Juice Tracker no Android Studio.
- Abra o
build.gradle.kts
do app. - No bloco
buildFeatures
, adicione uma flagcompose = true
.
buildFeatures {
//...
// Enable Jetpack Compose for this module
compose = true
}
Essa flag permite que o Android Studio funcione com o Compose. Você não realizou essa etapa nos codelabs anteriores, porque o Android Studio gera esse código automaticamente quando você cria um novo projeto de modelo do Compose no Android Studio.
- Abaixo de
buildFeatures
, adicione o blococomposeOptions
. - No bloco, defina
kotlinCompilerExtensionVersion
como"1.5.1"
para definir a versão do compilador Kotlin.
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
- Na seção
dependencies
, adicione dependências do Compose. Você precisa das dependências a seguir para adicionar o Compose a um app baseado em visualização. Essas dependências ajudam a integrar o Compose à atividade, adicionar a biblioteca de componentes de design do Compose, oferecer suporte aos temas do Jetpack e fornecer ferramentas para melhorar o suporte ao ambiente de desenvolvimento integrado.
dependencies {
implementation(platform("androidx.compose:compose-bom:2023.06.01"))
// other dependencies
// Compose
implementation("androidx.activity:activity-compose:1.7.2")
implementation("androidx.compose.material3:material3")
implementation("com.google.accompanist:accompanist-themeadapter-material3:0.28.0")
debugImplementation("androidx.compose.ui:ui-tooling")
}
Adicionar ComposeView
Uma ComposeView
é uma visualização do Android que pode hospedar conteúdo da interface do Jetpack Compose. Use setContent
para fornecer a função combinável do conteúdo para a visualização.
- Abra o
layout/list_item.xml
e confira a prévia na guia Split.
Ao final deste codelab, você vai substituir essa visualização por um elemento combinável.
- No
JuiceListAdapter.kt
, removaListItemBinding
de todos os lugares. Na classeJuiceListViewHolder
, substituabinding.root
porcomposeView
.
import androidx.compose.ui.platform.ComposeView
class JuiceListViewHolder(
private val onEdit: (Juice) -> Unit,
private val onDelete: (Juice) -> Unit
): RecyclerView.ViewHolder(composeView)
- Na pasta
onCreateViewHolder()
, atualize a funçãoreturn()
para que ela fique como este código:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JuiceListViewHolder {
return JuiceListViewHolder(
ComposeView(parent.context),
onEdit,
onDelete
)
}
- Na classe
JuiceListViewHolder
, exclua todas as variáveisprivate
e remova todo o código da funçãobind()
. A classeJuiceListViewHolder
agora terá esta aparência:
class JuiceListViewHolder(
private val onEdit: (Juice) -> Unit,
private val onDelete: (Juice) -> Unit
) : RecyclerView.ViewHolder(composeView) {
fun bind(juice: Juice) {
}
}
- Agora, é possível excluir as importações
com.example.juicetracker.databinding.ListItemBinding
eandroid.view.LayoutInflater
.
// Delete
import com.example.juicetracker.databinding.ListItemBinding
import android.view.LayoutInflater
- Exclua o arquivo
layout/list_item.xml
. - Selecione OK na caixa de diálogo Delete.
4. Adicionar uma função combinável
Agora, crie um elemento combinável que emita o item de lista. A função combinável usa Juice
e duas funções de callback para editar e excluir o item de lista.
- No
JuiceListAdapter.kt
, após a definição da classeJuiceListAdapter
, crie uma função combinável chamadaListItem()
. - Faça com que a função
ListItem()
aceite o objetoJuice
e um callback lambda para exclusão.
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ListItem(
input: Juice,
onDelete: (Juice) -> Unit,
modifier: Modifier = Modifier
) {
}
Observe a prévia do item de lista que você quer criar. Ela mostra um ícone e detalhes do suco, além de um botão de exclusão. Você vai implementar esses componentes em breve.
Criar o elemento combinável do ícone de suco
- No
JuiceListAdapter.kt
, depois do elemento combinávelListItem()
, crie outra função combinável chamadaJuiceIcon()
que usa umacolor
e umModifier
.
@Composable
fun JuiceIcon(color: String, modifier: Modifier = Modifier) {
}
- Na função
JuiceIcon()
, adicione variáveis para acolor
e a descrição do conteúdo, conforme mostrado no seguinte código:
@Composable
fun JuiceIcon(color: String, modifier: Modifier = Modifier) {
val colorLabelMap = JuiceColor.values().associateBy { stringResource(it.label) }
val selectedColor = colorLabelMap[color]?.let { Color(it.color) }
val juiceIconContentDescription = stringResource(R.string.juice_color, color)
}
Usando as variáveis colorLabelMap
e selectedColor
, você vai recuperar o recurso de cores associado à seleção do usuário.
- Adicione um layout
Box
para mostrar dois íconesic_juice_color
eic_juice_clear
, um sobre o outro. O íconeic_juice_color
tem uma tonalidade e está alinhado ao centro.
import androidx.compose.foundation.layout.Box
Box(
modifier.semantics {
contentDescription = juiceIconContentDescription
}
) {
Icon(
painter = painterResource(R.drawable.ic_juice_color),
contentDescription = null,
tint = selectedColor ?: Color.Red,
modifier = Modifier.align(Alignment.Center)
)
Icon(painter = painterResource(R.drawable.ic_juice_clear), contentDescription = null)
}
Como você já conhece a implementação de um elemento combinável, os detalhes sobre essa etapa não são fornecidos.
- Adicione uma função para visualizar
JuiceIcon()
. Transmita a cor comoYellow
.
import androidx.compose.ui.tooling.preview.Preview
@Preview
@Composable
fun PreviewJuiceIcon() {
JuiceIcon("Yellow")
}
Criar elementos combináveis de detalhes do suco
No JuiceListAdapter.kt
, é necessário adicionar outra função combinável para mostrar os detalhes do suco. Você também precisa de um layout de coluna para mostrar dois elementos combináveis Text
para o nome e a descrição, além de um indicador de nota. Para isso, siga estas etapas:
- Adicione uma função combinável com o nome
JuiceDetails()
, que usa um objetoJuice
e umModifier
, além de um elemento combinável de texto para o nome e outro para a descrição do suco, conforme mostrado no código abaixo:
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.text.font.FontWeight
@Composable
fun JuiceDetails(juice: Juice, modifier: Modifier = Modifier) {
Column(modifier, verticalArrangement = Arrangement.Top) {
Text(
text = juice.name,
style = MaterialTheme.typography.h5.copy(fontWeight = FontWeight.Bold),
)
Text(juice.description)
RatingDisplay(rating = juice.rating, modifier = Modifier.padding(top = 8.dp))
}
}
- Para resolver o erro de referência, crie uma função combinável chamada
RatingDisplay()
.
No sistema de visualização, você tem uma RatingBar
para mostrar a barra de nota a seguir. Como o Compose não tem um elemento combinável da barra de nota, é necessário implementar esse elemento do zero.
- Defina a função
RatingDisplay()
para mostrar as estrelas de acordo com a nota. Essa função combinável mostra o número de estrelas com base na classificação.
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.pluralStringResource
@Composable
fun RatingDisplay(rating: Int, modifier: Modifier = Modifier) {
val displayDescription = pluralStringResource(R.plurals.number_of_stars, count = rating)
Row(
// Content description is added here to support accessibility
modifier.semantics {
contentDescription = displayDescription
}
) {
repeat(rating) {
// Star [contentDescription] is null as the image is for illustrative purpose
Image(
modifier = Modifier.size(32.dp),
painter = painterResource(R.drawable.star),
contentDescription = null
)
}
}
}
Para criar o drawable de estrela no Compose, é necessário criar o recurso de vetor de estrelas.
- No painel Project, clique com o botão direito do mouse em drawable > New > Vector Asset.
- Na caixa de diálogo do Asset Studio, procure um ícone de estrela. Selecione o ícone de estrela preenchida.
- Mude o valor de cor da estrela para 625B71.
- Clique em Next > Finish.
- Um drawable aparece na pasta
res/drawable
.
- Adicione um elemento combinável de prévia para
JuiceDetails
.
@Preview
@Composable
fun PreviewJuiceDetails() {
JuiceDetails(Juice(1, "Sweet Beet", "Apple, carrot, beet, and lemon", "Red", 4))
}
Criar um elemento combinável do botão de exclusão
- No
JuiceListAdapter.kt
, adicione outra função combinável chamadaDeleteButton()
, que usa uma função de callback de lambda e um modificador. - Defina a lambda como o argumento
onClick
e transmita oIcon()
conforme mostrado no seguinte código:
import androidx.compose.ui.res.painterResource
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@Composable
fun DeleteButton(onDelete: () -> Unit, modifier: Modifier = Modifier) {
IconButton(
onClick = { onDelete() },
modifier = modifier
) {
Icon(
painter = painterResource(R.drawable.ic_delete),
contentDescription = stringResource(R.string.delete)
)
}
}
- Adicione uma função de prévia para o botão de exclusão.
@Preview
@Composable
fun PreviewDeleteIcon() {
DeleteButton({})
}
5. Implementar a função ListItem
Agora que você tem todos os elementos combináveis necessários para mostrar o item de lista, eles podem ser organizados em um layout. Observe a função ListItem()
definida na etapa anterior.
@Composable
fun ListItem(
input: Juice,
onEdit: (Juice) -> Unit,
onDelete: (Juice) -> Unit,
modifier: Modifier = Modifier
) {
}
No JuiceListAdapter.kt
, conclua as etapas a seguir para implementar a função ListItem()
.
- Adicione um layout
Row
dentro do lambdaMdc3Theme {}
.
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import com.google.accompanist.themeadapter.material3.Mdc3Theme
Mdc3Theme {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween
) {
}
}
- No lambda
Row
, chame os três elementos combináveis (JuiceIcon
,JuiceDetails
eDeleteButton
) que você criou como elementos filhos.
JuiceIcon(input.color)
JuiceDetails(input, Modifier.weight(1f))
DeleteButton({})
A transmissão do Modifier.
weight
(1f)
para o elemento combinável JuiceDetails()
garante que os detalhes do suco ocupem o espaço horizontal restante depois de medir os elementos filhos sem peso.
- Transmita a lambda
onDelete(input)
e o modificador com alinhamento superior como parâmetros para o elemento combinávelDeleteButton
.
DeleteButton(
onDelete = {
onDelete(input)
},
modifier = Modifier.align(Alignment.Top)
)
- Crie uma função de prévia para o elemento combinável
ListItem
.
@Preview
@Composable
fun PreviewListItem() {
ListItem(Juice(1, "Sweet Beet", "Apple, carrot, beet, and lemon", "Red", 4), {})
}
- Vincule o elemento combinável
ListItem
ao armazenador de visualização. ChameonEdit(input)
na função lambdaclickable()
para abrir a caixa de diálogo de edição quando houver um clique no item da lista.
Na classe JuiceListViewHolder
, dentro da função bind()
, você precisa hospedar o elemento combinável. Use a ComposeView
, que é uma visualização do Android que pode hospedar conteúdo da interface do Compose utilizando o método setContent
.
fun bind(input: Juice) {
composeView.setContent {
ListItem(
input,
onDelete,
modifier = Modifier
.fillMaxWidth()
.clickable {
onEdit(input)
}
.padding(vertical = 8.dp, horizontal = 16.dp),
)
}
}
- Execute o app e adicione seu suco favorito. Observe o item de lista do Compose.
.
Parabéns! Você acabou de criar seu primeiro app de interoperabilidade do Compose que usa elementos do Compose em um app baseado em visualização.
6. Acessar o código da solução
Para baixar o código do codelab concluído, use estes comandos git:
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-juice-tracker.git $ cd basic-android-kotlin-compose-training-juice-tracker $ git checkout views-with-compose
Se preferir, você pode baixar o repositório como um arquivo ZIP, descompactar e abrir no Android Studio.
Se você quiser conferir o código da solução, acesse o GitHub (link em inglês).
7. Saiba mais
Documentação do desenvolvedor Android
- Ferramentas para Compose | Jetpack Compose | Desenvolvedores Android
- APIs de interoperabilidade | Jetpack Compose | Desenvolvedores Android
- Estratégia de migração | Jetpack Compose | Desenvolvedores Android
Codelab [intermediário]