Prática: comportamento de clique

1. Antes de começar

Neste programa, você aprendeu a adicionar um botão a um app e fazer as modificações necessárias para responder a um clique no botão. Agora, está na hora de criar um app para praticar o que você aprendeu.

Você vai criar um app chamado Lemonade. Primeiro, leia os requisitos para entender melhor a aparência e o comportamento dele. Se quiser um desafio, você pode criar o app por conta própria depois disso. Caso tenha alguma dificuldade, leia as próximas seções para ver mais dicas e orientações sobre como entender e solucionar o problema.

Siga o exercício em um ritmo confortável para você. Leve o tempo que precisar para criar cada parte da funcionalidade do app. O código da solução do Lemonade está disponível no final deste módulo, mas recomendamos que você tente criar o app sem consultas. A solução fornecida não é a única maneira de criar o app Lemonade. Portanto, é totalmente válido criar de forma diferente, desde que os requisitos sejam atendidos.

Pré-requisitos

  • Saber criar um layout de IU simples no Compose com elementos de composição de texto e imagem.
  • Saber criar um app interativo que responda a um clique no botão.
  • Entender conceitos básicos de composição e recomposição.
  • Conhecer a linguagem de programação Kotlin, incluindo funções, variáveis, condicionais e lambdas.

O que vai ser necessário

  • Um computador com acesso à Internet e o Android Studio instalado.

2. Visão geral do app

Você vai ajudar a realizar nosso sonho de criar uma limonada digital. O objetivo é criar um app simples e interativo em que você possa tocar na imagem da tela para espremer limões até ter um copo de limonada. Isso pode ser interpretado como uma metáfora ou apenas uma forma divertida de passar o tempo.

dfcc3bc3eb43e4dd.png

Confira como o app funciona:

  1. Quando o usuário abrir o app pela primeira vez, ele verá um limoeiro. Será mostrado um texto pedindo para o usuário tocar na imagem do limoeiro para "pegar" um limão.
  2. Depois de tocar no limoeiro, um limão será mostrado. O usuário vai receber uma solicitação para tocar no limão e "espremer" a fruta para fazer a limonada. É necessário tocar no limão várias vezes. O número de toques necessários para espremer o limão varia e é gerado aleatoriamente (entre 2 e 4).
  3. Depois de tocar no limão quantas vezes forem necessárias, um copo refrescante de limonada será mostrado. O usuário precisa tocar no copo para "tomar" a limonada.
  4. Após tocar no copo de limonada, o usuário verá um copo vazio. É necessário tocar no copo vazio para começar de novo.
  5. Depois de tocar no copo vazio, o limoeiro será mostrado e o usuário vai poder começar o processo novamente. Mais limonada!

Confira a aparência do app nestas capturas de tela maiores:

Para cada etapa da limonada, há uma imagem, um texto e uma resposta diferente ao clique. Por exemplo, quando o usuário toca no limoeiro, o app mostra um limão.

Sua tarefa é criar o layout da IU do app e implementar a lógica para que o usuário possa passar por todas as etapas e fazer uma limonada.

3. Como começar

Criar um projeto

No Android Studio, crie um novo projeto com o modelo Empty Activity e os seguintes detalhes:

  • Name: Lemonade
  • Package name: com.example.lemonade
  • Minimum SDK: 24

Depois de criar o app e os builds do projeto, siga para a próxima seção.

Adicionar imagens

Você vai receber quatro arquivos de drawables vetoriais para usar no app Lemonade.

Siga estas etapas:

  1. Faça o download de um arquivo ZIP das imagens (link em inglês) para o app.
  2. Clique duas vezes no arquivo ZIP. Esta etapa descompacta as imagens em uma pasta.
  3. Adicione as imagens à pasta drawable do app. Caso não se lembre de como fazer isso, consulte o codelab Criar um app Dice Roller interativo.

A pasta do projeto vai ter a mesma aparência da captura de tela abaixo, em que os recursos lemon_drink.xml, lemon_restart.xml, lemon_squeeze.xml e lemon_tree.xml são mostrados no diretório res > drawable:

ccc5a4aa8a7e9fbd.png

  1. Clique duas vezes em um arquivo de drawable vetorial para abrir uma prévia da imagem.
  2. Selecione o painel Design (não as visualizações Code ou Split) para conferir a imagem em tamanho integral.

3f3a1763ac414ec0.png

Depois que os arquivos de imagem são incluídos no seu app, eles podem ser referenciados no código. Por exemplo, se o arquivo de drawable vetorial for chamado de lemon_tree.xml, você vai poder fazer referência a ele no código Kotlin usando o ID de recurso no formato R.drawable.lemon_tree.

Adicionar recursos de string

Adicione as seguintes strings ao projeto no arquivo res > values > strings.xml:

  • Tap the lemon tree to select a lemon
  • Keep tapping the lemon to squeeze it
  • Tap the lemonade to drink it
  • Tap the empty glass to start again

As strings a seguir também são necessárias para o projeto. Elas não são mostradas na interface do usuário, mas são usadas para a descrição de conteúdo das imagens no app. Adicione estas strings ao arquivo strings.xml do seu app:

  • Lemon tree
  • Lemon
  • Glass of lemonade
  • Empty glass

Caso você não se lembre de como declarar recursos de string no app, consulte o codelab Criar um app Dice Roller interativo ou a seção String. Dê a cada recurso de string um nome de identificador adequado para descrever o valor dele. Por exemplo, a string "Lemon" pode ser declarada no arquivo strings.xml com o nome de identificador lemon_content_description e, em seguida, referenciada no seu código usando o ID de recurso: R.string.lemon_content_description.

Etapas para fazer uma limonada

Agora você tem os recursos de string e de imagem necessários para implementar no app. Veja um resumo de cada etapa do app e o que será mostrado na tela.

Etapa 1:

  • Texto: Tap the lemon tree to select a lemon
  • Imagem: limoeiro (lemon_tree.xml)

b2b0ae4400c0d06d.png

Etapa 2:

  • Texto: Keep tapping the lemon to squeeze it
  • Imagem: limão (lemon_squeeze.xml)

7c6281156d027a8.png

Etapa 3:

  • Texto: Tap the lemonade to drink it
  • Imagem: copo cheio de limonada (lemon_drink.xml)

38340dfe3df0f721.png

Etapa 4:

  • Texto: Tap the empty glass to start again
  • Imagem: copo vazio (lemon_restart.xml)

e9442e201777352b.png

Deixar o visual mais refinado

Para que sua versão do app fique parecida com as capturas de tela finais, é necessário fazer mais alguns ajustes visuais:

  • Aumente o tamanho da fonte do texto para que ela fique maior que o tamanho padrão (por exemplo, 18sp).
  • Adicione mais espaço entre o texto e a imagem abaixo dele para que não fiquem próximos demais (por exemplo, 16dp).
  • Dê ao botão uma cor de destaque e cantos levemente arredondados para informar aos usuários que podem tocar na imagem.

Se quiser se desafiar, crie o restante do app com base na descrição de funcionamento dele. Se quiser mais orientações, continue para a próxima seção.

4. Planejar a criação do app

Ao criar um app, comece com uma versão que funcione minimamente bem. Depois, você pode adicionar mais funcionalidades gradualmente até ter todas as desejadas. Identifique uma pequena funcionalidade de ponta a ponta que você possa criar primeiro.

No app Lemonade, o principal é fazer a transição de uma etapa para outra com uma imagem e um texto diferentes a cada vez. Inicialmente, você pode ignorar o comportamento especial do estado de espremer, já que essa funcionalidade pode ser adicionada após a criação da base do app.

Veja abaixo uma proposta de panorama geral das etapas que você pode seguir para criar o app:

  1. Crie o layout da IU para a primeira etapa do preparo da limonada, que solicita que o usuário pegue um limão no limoeiro. Você pode ignorar a borda ao redor da imagem por enquanto, já que esse é um detalhe visual que pode ser adicionado mais tarde.

b2b0ae4400c0d06d.png

  1. Implemente o comportamento para que o app mostre a imagem de um limão e o texto correspondente quando o usuário tocar no limoeiro. Isso abrange as duas primeiras etapas da limonada.

adbf0d217e1ac77d.png

  1. Adicione o código para que o app mostre o restante das etapas quando o usuário tocar na imagem. Neste ponto, basta um toque no limão para fazer a transição para o copo de limonada.

Quatro caixas em uma linha horizontal, cada uma com uma borda verde. Cada caixa contém um número de 1 a 4. Uma seta aponta da caixa 1 para a 2, da 2 para a 3, da 3 para a 4 e da 4 de volta para a 1. Abaixo da caixa 1, há a imagem de um limoeiro e o texto "Tap the lemon tree to select a lemon" (Toque no limoeiro para pegar um limão). Abaixo da caixa 2, há a imagem de um limão e o texto "Keep tapping the lemon to squeeze it" (Continue tocando no limão até ele ser espremido). Abaixo da caixa 3, há a imagem de um copo de limonada e o texto "Tap the lemonade to drink it" (Toque na limonada para beber). Abaixo da caixa 4, há a imagem de um copo vazio e o texto "Tap the empty glass to start again" (Toque no copo vazio para começar de novo).

  1. Adicione um comportamento personalizado à etapa de espremer o limão para que o usuário precise "espremer", ou seja, tocar no limão um número específico de vezes gerado aleatoriamente (entre 2 e 4).

Quatro caixas em uma linha horizontal, cada uma com uma borda verde. Cada caixa contém um número de 1 a 4. Uma seta aponta da caixa 1 para a 2, da 2 para a 3, da 3 para a 4 e da 4 de volta para a 1. Uma outra seta aponta da caixa 2 de volta para si mesma com o texto "Random number of times" (Número aleatório de vezes). Abaixo da caixa 1, está a imagem do limoeiro e o texto correspondente. Abaixo da caixa 2, está a imagem do limão e o texto correspondente. Abaixo da caixa 3, está a imagem do copo de limonada e o texto correspondente. Abaixo da caixa 4, está a imagem do copo vazio e o texto correspondente.

  1. Finalize o app com quaisquer outros detalhes visuais necessários. Por exemplo, mude o tamanho da fonte e adicione uma borda às imagens para deixar o app mais refinado. Verifique se o app segue práticas recomendadas de programação, como as diretrizes de estilo de programação do Kotlin e a inclusão de comentários no código.

Se você conseguir usar estas etapas gerais para se orientar na implementação do Lemonade, crie o app por conta própria. Se precisar de mais orientações sobre cada uma dessas cinco etapas, siga para a próxima seção.

5. Implementar o app

Criar o layout da IU

Primeiro, modifique o app para que ele mostre a imagem do limoeiro e o texto correspondente, "Tap the lemon tree to select a lemon" (Toque no limoeiro para pegar um limão), no centro da tela. Precisa haver um espaço de 16dp entre o texto e a imagem abaixo dele.

b2b0ae4400c0d06d.png

Você pode usar este código inicial no arquivo MainActivity.kt:

package com.example.lemonade

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.lemonade.ui.theme.LemonadeTheme

class MainActivity : ComponentActivity() {
   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContent {
           LemonadeTheme {
               LemonApp()
           }
       }
   }
}

@Composable
fun LemonApp() {
   // A surface container using the 'background' color from the theme
   Surface(
       modifier = Modifier.fillMaxSize(),
       color = MaterialTheme.colorScheme.background
   ) {
       Text(text = "Hello there!")
   }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
   LemonadeTheme {
       LemonApp()
   }
}

Esse código é semelhante ao gerado automaticamente pelo Android Studio. No entanto, em vez de um elemento combinável Greeting(), há um elemento LemonApp() que não espera um parâmetro. O elemento combinável DefaultPreview() também foi atualizado para usar o LemonApp(). Assim, você pode conferir uma prévia do código com facilidade.

Depois de inserir esse código no Android Studio, modifique o elemento combinável LemonApp(), que deve ter o conteúdo do app. Confira algumas perguntas que podem orientar seu processo de raciocínio:

Implemente esta etapa para que o limoeiro e o texto sejam mostrados no app quando ele for aberto. Visualize o elemento de composição no Android Studio para ver a aparência da IU conforme você modifica o código. Execute o app para garantir que ele esteja parecido com a captura de tela mostrada anteriormente.

Quando terminar, volte a estas instruções para ver mais dicas sobre a adição de comportamentos ao tocar nas imagens.

Adicionar o comportamento de clique

Agora, você vai adicionar um código para que o limão seja mostrado com o texto Keep tapping the lemon to squeeze it (Toque no limão até ele ser espremido) quando o usuário tocar na imagem do limoeiro. Em outras palavras, quando você toca no limoeiro, o texto e a imagem mudam.

adbf0d217e1ac77d.png

Em etapas anteriores deste programa, você aprendeu a transformar um botão em um elemento clicável. No caso do app Lemonade, não há um combinável Button. No entanto, qualquer elemento pode ser transformado em clicável, não apenas botões. Basta especificar o modificador clickable. Para ver um exemplo, consulte a página de documentação do elemento clickable.

O que vai acontecer quando alguém clicar na imagem? O código para implementar esse comportamento não é trivial, então vamos revisitar outro app conhecido.

Analisar o app Dice Roller

Revise o código do app Dice Roller e observe como ele mostra diferentes imagens de dados com base no valor resultante:

MainActivity.kt no app Dice Roller

...

@Composable
fun DiceWithButtonAndImage(modifier: Modifier = Modifier) {
   var result by remember { mutableStateOf(1) }
   val imageResource = when(result) {
       1 -> R.drawable.dice_1
       2 -> R.drawable.dice_2
       3 -> R.drawable.dice_3
       4 -> R.drawable.dice_4
       5 -> R.drawable.dice_5
       else -> R.drawable.dice_6
   }
   Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
       Image(painter = painterResource(id = imageResource), contentDescription = result.toString())
       Button(onClick = { result = (1..6).random() }) {
          Text(stringResource(id = R.string.roll))
       }
   }
}

...

Responda a estas perguntas sobre o código do app Dice Roller:

  • O valor de qual variável determina a imagem de dado adequada para exibição?
  • Qual ação do usuário aciona a mudança dessa variável?

A função combinável DiceWithButtonAndImage() armazena o resultado mais recente na variável result, que foi definida com o elemento combinável remember e a função mutableStateOf() nesta linha de código:

var result by remember { mutableStateOf(1) }

Quando a variável result é atualizada para um novo valor, o Compose aciona a recomposição do elemento DiceWithButtonAndImage(), o que significa que ele será executado novamente. O valor result é lembrado nas recomposições. Portanto, quando o elemento de composição DiceWithButtonAndImage() é executado novamente, o valor result mais recente é usado. Aplicando uma instrução when no valor da variável result, o elemento de composição determina o novo ID do recurso drawable, que será mostrado pelo elemento Image.

Aplicar o que você aprendeu ao app Lemonade

Agora, responda a perguntas semelhantes sobre o app Lemonade:

  • Existe uma variável que pode ser usada para determinar qual texto e imagem serão mostrados na tela? Defina essa variável no código.
  • Você pode usar condicionais em Kotlin para que o app tenha um comportamento diferente dependendo do valor dessa variável? Se for o caso, inclua essa instrução condicional no código.
  • Qual ação do usuário aciona a mudança dessa variável? Encontre o local em que isso acontece no código. Faça as modificações necessárias para atualizar a variável.

Esta seção pode ser difícil de implementar e requer mudanças em várias partes do código para funcionar bem. Não desanime se o app não funcionar imediatamente. Lembre-se de que há várias maneiras corretas de implementar esse comportamento.

Quando terminar, execute o app e verifique se ele está funcionando. Ao ser aberto, o app precisa mostrar a imagem do limoeiro e o texto correspondente. Um único toque na imagem do limoeiro atualiza o texto e mostra a imagem do limão. Por enquanto, um toque na imagem do limão não tem efeito algum.

Adicionar as etapas restantes

Agora, o app pode mostrar duas das etapas de preparo da limonada. Neste momento, seu elemento de composição LemonApp() pode estar parecido com o snippet de código a seguir. Tudo bem se o código for um pouco diferente, desde que o comportamento no app seja o mesmo.

MainActivity.kt

...
@Composable
fun LemonApp() {
   // Current step the app is displaying (remember allows the state to be retained
   // across recompositions).
   var currentStep by remember { mutableStateOf(1) }

   // A surface container using the 'background' color from the theme
   Surface(
       modifier = Modifier.fillMaxSize(),
       color = MaterialTheme.colorScheme.background
   ) {
       when (currentStep) {
           1 -> {
               Column (
                   horizontalAlignment = Alignment.CenterHorizontally,
                   verticalArrangement = Arrangement.Center,
                   modifier = Modifier.fillMaxSize()
               ){
                   Text(text = stringResource(R.string.lemon_select))
                   Spacer(modifier = Modifier.height(32.dp))
                   Image(
                       painter = painterResource(R.drawable.lemon_tree),
                       contentDescription = stringResource(R.string.lemon_tree_content_description),
                       modifier = Modifier
                           .wrapContentSize()
                           .clickable {
                               currentStep = 2
                           }
                   )
               }
           }
           2 -> {
               Column (
                   horizontalAlignment = Alignment.CenterHorizontally,
                   verticalArrangement = Arrangement.Center,
                   modifier = Modifier.fillMaxSize()
               ){
                   Text(text = stringResource(R.string.lemon_squeeze))
                   Spacer(modifier = Modifier.height(32
                       .dp))
                   Image(
                       painter = painterResource(R.drawable.lemon_squeeze),
                       contentDescription = stringResource(R.string.lemon_content_description),
                       modifier = Modifier.wrapContentSize()
                   )
               }
           }
       }
   }
}
...

Agora, vamos adicionar as outras etapas para fazer a limonada. Um único toque na imagem leva o usuário à etapa seguinte do preparo, com texto e imagem atualizados. Você terá que mudar o código para que ele fique mais flexível e processe todas as etapas do app, não apenas as duas primeiras.

Quatro caixas em uma linha horizontal, cada uma com uma borda verde. Cada caixa contém um número de 1 a 4. Uma seta aponta da caixa 1 para a 2, da 2 para a 3, da 3 para a 4 e da 4 de volta para a 1. Abaixo da caixa 1, há a imagem de um limoeiro e o texto "Tap the lemon tree to select a lemon" (Toque no limoeiro para pegar um limão). Abaixo da caixa 2, há a imagem de um limão e o texto "Keep tapping the lemon to squeeze it" (Continue tocando no limão até ele ser espremido). Abaixo da caixa 3, há a imagem de um copo de limonada e o texto "Tap the lemonade to drink it" (Toque na limonada para beber). Abaixo da caixa 4, há a imagem de um copo vazio e o texto "Tap the empty glass to start again" (Toque no copo vazio para começar de novo).

Para ter um comportamento diferente a cada clique na imagem, personalize o comportamento clicável. Mais especificamente, a lambda que é executada quando há um clique na imagem precisa saber qual será a etapa seguinte.

Talvez você perceba que há código repetido no app para cada etapa de preparo da limonada. Para a instrução when no snippet de código anterior, o código da instância 1 é muito semelhante ao da 2, com pequenas diferenças. Se for útil, crie uma nova função de composição chamada LemonTextAndImage(), por exemplo, para mostrar o texto acima de uma imagem na IU. Ao criar uma nova função de composição que recebe parâmetros de entrada, você tem uma função reutilizável útil em vários cenários, desde que as entradas transmitidas sejam modificadas. É seu trabalho descobrir quais são os parâmetros da entrada. Depois de criar essa função combinável, atualize o código atual para que ela seja chamada em locais relevantes.

Outra vantagem de ter um elemento de composição separado, como LemonTextAndImage(), é que o código fica mais organizado e robusto. Ao chamar LemonTextAndImage(), você vai ter a certeza de que o texto e a imagem serão atualizados para os novos valores. Caso o código não seja criado dessa forma, é fácil deixar passar acidentalmente um caso em que um texto atualizado é mostrado com a imagem errada.

Mais uma dica: você pode até mesmo transmitir uma função lambda para um elemento de composição. Use a notação do tipo de função para especificar o que será transmitido. No exemplo a seguir, um elemento de composição WelcomeScreen() é definido e aceita dois parâmetros de entrada: uma string name e uma função onStartClicked() do tipo () -> Unit. Isso significa que a função não recebe valores de entrada (os parênteses vazios antes da seta) e não tem valor de retorno (o Unit após a seta). Qualquer função correspondente a esse tipo () -> Unit pode ser usada para definir o gerenciador onClick desse Button. Quando o botão recebe um clique, a função onStartClicked() é chamada.

@Composable
fun WelcomeScreen(name: String, onStartClicked: () -> Unit) {
    Column {
        Text(text = "Welcome $name!")
        Button(
            onClick = onStartClicked
        ) {
            Text("Start")
        }
    }
}

Transmitir um lambda para um elemento de composição é um padrão útil, já que o elemento WelcomeScreen() pode ser reutilizado em diferentes cenários. O nome do usuário e o comportamento onClick do botão podem ser diferentes a cada uso porque são transmitidos como argumentos.

Com essas novas informações, volte ao código para adicionar ao app as etapas restantes de preparo da limonada.

Volte aqui se quiser mais orientações sobre como adicionar lógica personalizada para espremer o limão um número aleatório de vezes.

Adicionar a lógica para espremer

Bom trabalho! Agora, você tem a base do app. Um toque na imagem faz com que você passe de uma etapa para a próxima. É hora de adicionar o comportamento de espremer o limão várias vezes para fazer limonada. A quantidade de vezes que o usuário precisa espremer, ou seja, tocar no limão será um número aleatório entre 2 e 4 (incluindo esses dois valores). Esse número aleatório muda sempre que o usuário pega um novo limão no limoeiro.

Quatro caixas em uma linha horizontal, cada uma com uma borda verde. Cada caixa contém um número de 1 a 4. Uma seta aponta da caixa 1 para a 2, da 2 para a 3, da 3 para a 4 e da 4 de volta para a 1. Uma outra seta aponta da caixa 2 de volta para si mesma com o texto "Random number of times" (Número aleatório de vezes). Abaixo da caixa 1, há a imagem de um limoeiro e o texto correspondente. Abaixo da caixa 2, está a imagem do limão e o texto correspondente. Abaixo da caixa 3, está a imagem do copo de limonada e o texto correspondente. Abaixo da caixa 4, está a imagem do copo vazio e o texto correspondente.

Veja algumas perguntas para orientar seu processo de raciocínio:

  • Como gerar números aleatórios no Kotlin?
  • Em que ponto do código o número aleatório precisa ser gerado?
  • Como garantir que o usuário tocou no limão o número de vezes necessário antes de avançar para a próxima etapa?
  • É necessário que alguma variável seja armazenada com o elemento de composição remember para que os dados não sejam redefinidos sempre que a tela for redesenhada?

Quando terminar de implementar essa mudança, execute o app. Verifique se é preciso tocar na imagem do limão várias vezes para acessar a próxima etapa e se a quantidade de toques necessários a cada preparo é um número aleatório entre 2 e 4. Se um único toque na imagem do limão fizer o copo de limonada ser mostrado, retorne ao código para ver o que está faltando e tente novamente.

Volte aqui se quiser mais orientações sobre a finalização do app.

Finalizar o app

Estamos quase lá! Adicione os últimos detalhes para dar os toques finais ao app.

Veja mais uma vez as capturas de tela finais com a aparência do app:

  • Centralize o texto e as imagens vertical e horizontalmente na tela.
  • Defina o tamanho da fonte do texto como 18sp.
  • Adicione um espaço de 16dp entre o texto e a imagem.
  • Adicione uma borda fina de 2dp ao redor das imagens, com cantos levemente arredondados de 4dp. A borda tem um valor RGB (link em inglês) de 105 para vermelho, 205 para verde e 216 para azul. Pesquise no Google para ver exemplos de como adicionar uma borda. Ou consulte a documentação Borda.

Quando você concluir essas mudanças, execute o app e faça uma comparação com as capturas de tela finais para confirmar se tudo está certo.

Como parte das práticas recomendadas de programação, volte e adicione comentários ao código para que qualquer pessoa entenda seu processo de criação com mais facilidade. Na parte de cima do arquivo do código, remova todas as instruções de importação não utilizadas. Confira se o código segue o Guia de estilo do Kotlin. Todos esses esforços vão ajudar a deixar seu código mais legível para outras pessoas e mais fácil de manter.

Muito bem! Você fez um ótimo trabalho na implementação do app Lemonade. Esse foi um app desafiador, com várias etapas para aprender. Agora você pode se recompensar com um delicioso copo de limonada. Saúde!

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

Faça o download do código da solução:

Uma alternativa seria clonar o repositório do GitHub:

$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-lemonade.git

Lembre-se de que seu código não precisa ser idêntico à solução, já que existem várias maneiras de implementar o app.

Você também pode procurar o código no repositório do app Lemonade no GitHub (link em inglês).