Adicionar uma lista rolável

1. Antes de começar

Neste codelab, você aprenderá a criar uma lista rolável no app usando o Jetpack Compose.

Você vai trabalhar com o app Affirmations, que mostra uma lista de afirmações combinadas com belas imagens para deixar seu dia mais positivo.

Os dados já estão disponíveis. Tudo o que você precisa fazer é mostrá-los na interface.

Pré-requisitos

  • Familiaridade com listas no Kotlin
  • Experiência em criação de layouts com o Jetpack Compose
  • Saber executar apps em um dispositivo ou emulador

O que você vai aprender

  • Como criar um card do Material Design usando o Jetpack Compose.
  • Como criar uma lista rolável usando o Jetpack Compose.

O que você vai criar

  • Partindo de um app já existente, você vai adicionar uma lista rolável à interface

O produto final ficará assim:

f6f09800b74f4700.png

Pré-requisitos

  • Um computador com acesso à Internet, um navegador da Web e o Android Studio
  • Acesso ao GitHub

baixe o código inicial

No Android Studio, abra a pasta basic-android-kotlin-compose-training-affirmations.

  1. Navegue até a página do repositório do GitHub fornecida para o projeto.
  2. Verifique se o nome da ramificação corresponde ao especificado no codelab. Por exemplo, na captura de tela a seguir, o nome da ramificação é main.

1e4c0d2c081a8fd2.png

  1. Na página do GitHub do projeto, clique no botão Code, que vai mostrar uma janela pop-up.

1debcf330fd04c7b.png

  1. Na janela pop-up, clique no botão Download ZIP para salvar o projeto no seu computador. Aguarde a conclusão do download.
  2. Localize o arquivo no computador. Geralmente ele é salvo na pasta Downloads.
  3. Clique duas vezes para descompactar o arquivo ZIP. Isso cria uma nova pasta com os arquivos do projeto.

Abrir o projeto no Android Studio

  1. Inicie o Android Studio.
  2. Na janela Welcome to Android Studio, clique em Open.

d8e9dbdeafe9038a.png

Observação: caso o Android Studio já esteja aberto, selecione a opção File > Open.

8d1fda7396afe8e5.png

  1. No navegador de arquivos, vá até a pasta descompactada do projeto, que provavelmente está na pasta Downloads.
  2. Clique duas vezes nessa pasta do projeto.
  3. Aguarde o Android Studio abrir o projeto.
  4. Clique no botão Run 8de56cba7583251f.png para criar e executar o app. Confira se ele foi criado da forma esperada.

2. Criar uma classe de dados do item da lista

Criar uma classe de dados para uma afirmação

Em apps Android, as listas são compostas por itens. Para dados únicos, isso pode ser algo simples, como uma string ou um número inteiro. Para itens de lista com vários dados, como imagem e texto, você vai precisar de uma classe que contenha todas essas propriedades. As classes de dados são um tipo de classe que contém apenas propriedades e podem fornecer alguns métodos utilitários para trabalhar com essas propriedades.

  1. Crie um novo pacote em com.example.affirmations. 4a51cb670bbec405.png.

Nomeie o novo pacote como model. O pacote de modelo vai conter o modelo de dados que será representado por uma classe de dados. Essa classe de dados será composta por propriedades que representam as informações relevantes para o que será uma "Afirmação", que consiste em um recurso de string e um de imagem. Os pacotes são diretórios que contêm classes e até mesmo outros diretórios.

9ea1f8880ca90ea0.png

  1. Crie uma nova classe no pacote com.example.affirmations.model. a9515a8b47715a22.png

Dê o nome Affirmation à nova classe e defina-a como Data Class.

b36be7f428fd1672.png

  1. Cada Affirmation consiste em uma imagem e uma string. Crie duas propriedades val na classe de dados Affirmation. Uma delas precisa ter o nome stringResourceId e a outra, imageResourceId. Ambas precisam ser números inteiros.

Affirmation.kt

data class Affirmation(
   val stringResourceId: Int,
   val imageResourceId: Int
)
  1. Marque a propriedade stringResourceId com a anotação @StringRes e marque imageResourceId com @DrawableRes. O stringResourceId representa um ID para o texto da afirmação armazenado em um recurso de string. O imageResourceId representa um ID para a imagem da afirmação armazenada em um recurso drawable.

Affirmation.kt

data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)
  1. Agora, abra o arquivo Datasource.kt no pacote com.example.affirmations.data e remova a marca de comentário do conteúdo da classe Datasource.

Datasource.kt

class Datasource() {
   fun loadAffirmations(): List<Affirmation> {
       return listOf<Affirmation>(
           Affirmation(R.string.affirmation1, R.drawable.image1),
           Affirmation(R.string.affirmation2, R.drawable.image2),
           Affirmation(R.string.affirmation3, R.drawable.image3),
           Affirmation(R.string.affirmation4, R.drawable.image4),
           Affirmation(R.string.affirmation5, R.drawable.image5),
           Affirmation(R.string.affirmation6, R.drawable.image6),
           Affirmation(R.string.affirmation7, R.drawable.image7),
           Affirmation(R.string.affirmation8, R.drawable.image8),
           Affirmation(R.string.affirmation9, R.drawable.image9),
           Affirmation(R.string.affirmation10, R.drawable.image10))
   }
}

3. Adicionar uma lista ao seu app

Criar um card de item da lista

O app precisa exibir uma lista de afirmações. A primeira etapa na configuração da interface para exibir uma lista é criar um item correspondente. Cada item da afirmação é composto por uma imagem e uma string. Os dados de cada um desses itens vêm com o código inicial, e você vai criar o componente de interface para mostrar cada item.

O item é um elemento Card combinável, que contém os elementos Image e Text. No Compose, Card é uma plataforma que exibe conteúdo e ações em um único contêiner. O card de afirmação ficará assim:

95111184aed54fa3.png

O card mostra uma imagem com texto abaixo. Esse layout vertical pode ser alcançado usando um elemento Column combinável encapsulado em um Card. Você pode fazer um teste ou seguir as etapas abaixo para fazer isso.

  1. Abrir o arquivo MainActivity.kt.

1e348baaf91552f4.png

  1. Crie um novo método abaixo do método AffirmationApp(), chamado AffirmationCard(), e adicione a anotação @Composable.

MainActivity.kt

@Composable
fun AffirmationApp() {
   val context = LocalContext.current
   AffirmationsTheme {
    
   }
}

@Composable
fun AffirmationCard() {
  
}
  1. Edite a assinatura do método para usar um objeto Affirmation como parâmetro. O objeto Affirmation vem do pacote model.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation) {
  
}
  1. Adicione um parâmetro modifier à assinatura. Defina um valor padrão de Modifier para o parâmetro.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  
}
  1. No método AffirmationCard, chame o elemento Card combinável. Transmita estes parâmetros: modifier e elevation. Transmita um objeto Modifier com o atributo padding definido como 8.dp para o parâmetro modifier. Transmita um valor de 4.dp para o elevation. A propriedade elevation será abordada com mais detalhes posteriormente.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
  }
}
  1. Adicione um elemento Column combinável ao Card. Os itens em um elemento Column combinável se organizam verticalmente na interface. Isso permite que você posicione uma imagem acima do texto associado. Por outro lado, uma Row combinável organiza os itens na horizontal.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
    Column {
    }
  }
}
  1. Adicione um elemento Image combinável ao corpo da lambda do Column. Não esqueça que uma Image combinável sempre exige um recurso para exibição e uma contentDescription. O recurso precisa ser um painterResource transmitido ao parâmetro painter. O método painterResource carregará drawables vetoriais ou formatos de recursos rasterizados, como PNGs. Além disso, transmita um stringResource para o parâmetro contentDescription.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId)
      )
    }
  }
}
  1. Além dos parâmetros painter e contentDescription, transmita um modifier e um contentScale. Um contentScale determina como a imagem deve ser dimensionada e exibida. O objeto Modifier precisa ter o atributo fillMaxWidth definido e uma altura de 194.dp. contentScale precisa ser ContentScale.Crop.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId),
        modifier = Modifier
          .fillMaxWidth()
          .height(194.dp),
        contentScale = ContentScale.Crop
      )
    }
  }
}
  1. Dentro da Column, crie um Text combinável após o elemento Image. Transmita um stringResource da affirmation.stringResourceId ao parâmetro text, transmita um objeto Modifier com o atributo padding definido como 16.dp e defina um tema de texto transmitindo MaterialTheme.typography.h6 ao parâmetro style.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId),
        modifier = Modifier
          .fillMaxWidth()
          .height(194.dp),
        contentScale = ContentScale.Crop
      )
      Text(
        text = stringResource(affirmation.stringResourceId),
        modifier = Modifier.padding(16.dp),
        style = MaterialTheme.typography.h6
      )
    }
  }
}

Visualizar o elemento AffirmationCard combinável

Você trabalhou duro para criar o card, que é a parte principal da interface do app Affirmations. Para verificar se o card está correto, crie um elemento combinável que pode ser visualizado sem precisar abrir o app inteiro.

  1. Crie um método particular chamado AffirmationCardPreview(). Adicione as anotações @Preview e @Composable ao método.

MainActivity.kt

@Preview 
@Composable
private fun AffirmationCardPreview() {
}
  1. No método, chame o elemento AffirmationCard combinável e transmita um novo objeto Affirmation com o recurso de string R.string.affirmation1 e o recurso drawable R.drawable.image1 transmitido ao construtor.

MainActivity.kt

@Preview 
@Composable
private fun AffirmationCardPreview() {
  AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
  1. Abra a guia Split para visualizar o AffirmationCard. Se necessário, clique em Build & Refresh no painel Design para exibir a visualização. 84904da4a33413ce.png

Criar a lista

O componente do item é o elemento fundamental da lista. Depois que o item da lista for criado, ele poderá ser usado para criar o componente da lista.

  1. Crie um método com o nome AffirmationList(), adicione a anotação @Composable e declare uma List de objetos Affirmation como um parâmetro na assinatura do método.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>) {
}
  1. Declare um objeto modifier como um parâmetro na assinatura do método com um valor padrão de Modifier.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
  1. No Jetpack Compose, uma lista rolável pode ser feita usando a função LazyColumn. A diferença entre uma LazyColumn e uma Column é que uma Column precisa ser usada quando há poucos itens para mostrar, já que o Compose carrega todos de uma só vez. Uma Column só pode conter um número predefinido ou fixo de elementos combináveis. Uma LazyColumn pode adicionar conteúdo sob demanda, o que é bom para listas longas, especialmente quando o tamanho da lista é desconhecido. Uma LazyColumn também oferece rolagem por padrão, sem código adicional. Declare uma LazyColumn combinável dentro do método AffirmationList().

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
  }
}
  1. No corpo da lambda da LazyColumn, chame o método items() e transmita a affirmationList. O método items() é como você adiciona itens à LazyColumn. Esse método é algo exclusivo desse elemento combinável e não é uma prática comum na maioria dos elementos.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){
    }
  }
}
  1. Uma chamada para o método items() requer uma função lambda. Nessa função, especifique um parâmetro de affirmation que representa um item de afirmação da affirmationList.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
    }
  }
}
  1. Para cada afirmação da lista, chame o elemento AffirmationCard() combinável e transmita a ele a affirmation.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
      AffirmationCard(affirmation)
    }
  }
}

Exibir a lista

  1. Na lambda, chame o elemento AffirmationList combinável e transmita DataSource().loadAffirmations() para o parâmetro affirmationList.

MainActivity.kt

@Composable
fun AffirmationApp() {
   AffirmationsTheme {
       Scaffold(
           content = {
               AffirmationList(affirmationList = Datasource().loadAffirmations())
           }
       )
   }
}

Execute o app Affirmations em um dispositivo ou emulador e confira o produto final.

f6f09800b74f4700.png

4. Acessar o código da solução

Se você quiser conferir o código da solução, acesse o GitHub.

  1. Navegue até a página do repositório do GitHub fornecida para o projeto.
  2. Verifique se o nome da ramificação corresponde ao especificado no codelab. Por exemplo, na captura de tela a seguir, o nome da ramificação é main.

1e4c0d2c081a8fd2.png

  1. Na página do GitHub do projeto, clique no botão Code, que vai mostrar uma janela pop-up.

1debcf330fd04c7b.png

  1. Na janela pop-up, clique no botão Download ZIP para salvar o projeto no seu computador. Aguarde a conclusão do download.
  2. Localize o arquivo no computador. Geralmente ele é salvo na pasta Downloads.
  3. Clique duas vezes para descompactar o arquivo ZIP. Isso cria uma nova pasta com os arquivos do projeto.

Abrir o projeto no Android Studio

  1. Inicie o Android Studio.
  2. Na janela Welcome to Android Studio, clique em Open.

d8e9dbdeafe9038a.png

Observação: caso o Android Studio já esteja aberto, selecione a opção File > Open.

8d1fda7396afe8e5.png

  1. No navegador de arquivos, vá até a pasta descompactada do projeto, que provavelmente está na pasta Downloads.
  2. Clique duas vezes nessa pasta do projeto.
  3. Aguarde o Android Studio abrir o projeto.
  4. Clique no botão Run 8de56cba7583251f.png para criar e executar o app. Confira se ele é criado da forma esperada.

5. Conclusão

Agora você já sabe como criar cards, itens de lista e listas roláveis usando o Jetpack Compose. Essas são apenas ferramentas básicas para criar uma lista. Você pode soltar a criatividade e personalizar itens da lista como quiser.

Resumo

  • Use os elementos combináveis Card para criar itens de lista.
  • Modifique a interface contida em um elemento combináveis Card.
  • Crie uma lista rolável usando a LazyColumn combinável.
  • Crie uma lista usando itens de lista personalizados