Alura > Cursos de Mobile > Cursos de Android > Conteúdos de Android > Primeiras aulas do curso Jetpack Compose: formulário e gerenciamento de estado

Jetpack Compose: formulário e gerenciamento de estado

Implementando formulário dos produtos - Apresentação

Olá, pessoal! Eu sou Alex Felipe, instrutor da Alura, e vou apresentar para vocês o curso Jetpack Compose: Formulário e gerenciamento de estado. A partir desse curso eu presumirei que vocês têm alguns pré-requisitos necessários para dar continuidade ao conteúdo e evoluir mais uma habilidade com o Jetpack Compose.

Pré-requisitos:

O principal pré-requisito é o conhecimento sobre estados. Por exemplo, no nosso aplicativo Aluvery, ao clicarmos no campo de busca, na parte superior do app, e digitarmos algum texto, como "cerveja", ele filtra os resultados. Para conseguir fazer isso, é necessário entender sobre estados.

Caso já cumpram estes pré-requisitos, podem seguir o curso. Já se não tiverem ideia de como isso funciona, mas querem aprender, aqui na Alura temos o curso Jetpack Compose: utilizando lazy layouts e estados, onde vocês descobrirão mais sobre os estados.

Inclusive, este curso de formulário e gerenciamento de estados é a continuação do curso que implementa o aplicativo Aluvery. Vocês podem acessar a página do GitHub do projeto jetpack-compose-lazy-layouts-e-estados para mais informações.

Projeto

Agora que sabemos os pré-requisitos, conheceremos o projeto e os tópicos de conhecimento do curso. Assim descobriremos o quanto vamos evoluir com este curso.

A primeira coisa que teremos de diferente no aplicativo é o botão redondo com um sinal de "+" que está no canto inferior direito da tela. Ele é conhecido como Floating Action Button. Ao clicarmos nele, somos direcionados para outra tela, então aprenderemos como fazer a navegação entre telas quando trabalhamos com Jetpack Compose.

Tela inicial do Aluvery, aplicativo criado nos cursos passados. Uma seta vermelha aponta para o botão redondo no canto inferior direito da tela, flutuando sobre o card do item "Sorvete". O botão está no tom de azul-índigo do tema e tem o sinal de "+" dentro dele.

A tela nova que teremos é uma formulário, que terá uma ação para criar novos produtos. Sendo assim, aprenderemos a implementar um formulário, tanto na parte visual quanto funcional.

Tela de formulário. Na parte superior esquerda está o título "Criando o produto", seguido dos campos do formulário. De cima para baixo a ordem é "Url da imagem", "Nome", "Preço", "Descrição". Por fim, abaixo dos campos há um botão retangular escrito "Salvar", ocupando toda a largura da tela.

Para criarmos um produto, como uma "salada de frutas", nós preenchemos o nome no segundo campo e podemos adicionar o link de uma imagem no primeiro campo. Eu acessei o site Pexels, que é um diretório de imagens gratuitas separei o link dessa imagem de salada de frutas.

Na imagem tem uma tábua de madeira com várias frutas em cima, algumas estão cortadas, como a manga e a laranja, e outras estão inteiras, como framboesa, amora e mirtilo. Então copiamos o link dessa imagem pressionamos o campo e surge a opção "Paste" para colá-lo. Com isso, temos um preview da imagem na parte superior da tela, que aprenderemos como implementar.

Além disso, aprenderemos técnicas de experiência de uso, como fazer o scroll funcionar corretamente, o que notaremos que precisa de uma certa atenção no Compose. Também vamos descobrir que os teclados virtuais são diferentes, por exemplo, enquanto a tecla à esquerda da barra de espaço no teclado do campo de URL é um traço, na do campo de Nome é uma vírgula.

Existem diferentes tipos de teclado que podemos explorar no Compose, e vamos conhecê-los, como o teclado do campo Preço, que é um teclado numérico. Então percebam que são vários detalhes que iremos implementar no nosso código, como o fato de podemos adicionarmos preços com valor decimal, adicionando um ponto (.) para separar a casa dos centavos.

O último campo, após o preço, é o da descrição. Quando clicamos nele, as letras começam em maiúsculo e, ao digitarmos uma informação, após a primeira letra maiúscula, as demais se tornam minúsculas. Ao pressionarmos "Enter", quebramos a linha e as letras voltam a ser maiúsculas.

Aprenderemos a como fazer tudo isso no Compose, inclusive a como clicar no botão de salvar, no final do formulário, e sermos redirecionados para tela anterior, mantendo o seu estado, ou seja, do resultado da busca por "cerveja". Ao apagarmos a busca, o registro do nosso produto aparece no começo da tela, na seção "Todos produtos".

Então aprenderemos que existem várias técnicas e precisamos aplicá-las para alcançarmos esse resultado no nosso aplicativo, conseguindo que tudo funcione da maneira adequada. Isso significa que além do app ser executando corretamente, teremos compreensão do nosso código.

Com isso conseguiremos fazer uma manutenção e um crescimento do app com mais facilidade. Para tudo isso, usaremos essas técnicas de gerenciamento de estados, que entenderemos que é muito comum no Jetpack Compose e será muito comum no seu dia a dia.

Agora que passei todas as informações, espero que estejam animados e animadas para começarem esse conteúdo.

Conto com a presença de vocês na primeira aula!

Implementando formulário dos produtos - Apresentando a tela de formulário

Como primeiro passo, conhecermos funcionalidades que iremos adicionar no projeto. Antes de verificar essas funcionalidades, é muito importante ressaltar que esse projeto é a continuação do curso Jetpack Compose: utilizando lazy layouts e estados.

Nesse projeto já temos acesso às seções de produto, ao campo de busca de produtos e à filtragem dos resultados. Então esse é o comportamento que vocês encontrarão no app ao iniciar esse conteúdo.

Figma

Sendo assim, vamos acessar ao Figma, onde concentramos as funcionalidades do aplicativo. O primeiro ponto a destacar é que agora temos um botão circular com um sinal de "+" no canto inferior direito de todas as telas que tínhamos anteriormente.

É um pouco difícil visualizá-lo nas duas primeiras telas apresentadas no Figma, porque ele está sobreposto à header do item de produto e ambos são azul-índigo, portanto não há contraste de cor. Já na terceira tela, que é quando fazemos o filtro, se sobrepõe a um fundo branco e a uma parte lilás do cartão, então temos uma visibilidade melhor.

Esse botão é conhecido como Floating Action Button, e a partir dele teremos acesso a uma nova tela. Essa tela também será um objetivo do nosso curso, e ela está demonstrada nas duas últimas imagens, da esquerda para direita, do protótipo do Figma.

Portanto, ao clicarmos no floating Action Button na tela inicial, seremos direcionados para essa nova tela, que contém o formulário do nosso produto. A partir dessa tela, permitiremos a criação de novos produtos, passando as informações de "Url da imagem", "Nome", "Preço" e a "Descrição".

Notamos que essa tela tem dois estados, por isso ela é representada em duas imagens. O primeiro estado corresponde ao formulário quando não está preenchido e o segundo estado corresponde à quando preenchemos a informação da URL. Com isso, uma caixa surge na parte superior do formulário, acima de todos os campos, contendo o preview da imagem.

Protótipo do Figma demonstrando o funcionamento da tela de formulário. Na imagem temos duas versões da tela. A primeira, que está à esquerda, tem formulário descrito no vídeo passado. A segunda, que está à direita, tem um retângulo cinza entre o título "Criando o produto" e o campo "Url da imagem". Esse retângulo representa o espaço onde fica o preview da imagem. Além disso, no campo "Url da imagem" está escrito "teste".

Essas são as funcionalidades que implementaremos no curso. Descobriremos todos os detalhes durante a implementação, mas é bom visualizarmos quais serão nossos objetivos.

Dado que precisaremos dessa tela para implementar o formulário do produto, primeiramente criaremos o código que nos permite apresentar esse conteúdo. Precisaremos acessar essa tela a partir de um fluxo, então criaremos uma Activity para manter o conteúdo visual dessa tela essa tela, sendo esse o nosso primeiro objetivo.

Criando a Activity

Voltando ao Android Studio, criaremos essa Activity da mesma forma que criamos o sistema de views. Então navegaremos para o pacote onde queremos deixar nossa Activity e faremos todo o processo de configuração, criando a classe, configurando o manifesto e assim por diante. A diferença é que não utilizaremos os arquivos de XML para layout, e sim o Compose.

Portanto vamos navegar para "app > java > ui" e usaremos o atalho "Alt + Insert" para criarmos o nosso pacote. No menu, pesquisaremos por "package" (pacote) e selecionaremos essa opção. Depois escreveremos "activities" na janela que surge no centro da tela, porque deixaremos todas as activities do nosso projeto nesse pacote.

Sendo assim, moveremos o MainActivity.kt, que também está no pacote "ui", para o pacote "activities", e para isso vamos clicar no botão "Refactor" no centro inferior da janela "Move", que surge no centro da tela. Assim fizemos nossa primeira refatoração, migrando a MainActivity.kt para o pacote "activities".

Nosso próximo passo é criar a nova Activity, que representará o formulário. Para isso, com o pacote "activities" selecionado, pressionamos "Alt + Insert" novamente e pesquisaremos por "kotlin" no menu. Selecionamos "Kotlin Class/File" para criarmos um arquivo em Kotlin, porque não usaremos o template que cria os layouts em XML.

Na janela "New Kotlin Class/File", que abre no centro da tela, deixaremos a opção "Class" (Classe) selecionada. Além disso, escreveremos "ProductFormActivity" para ser o nome da nossa Activity, uma vez que será um formulário de produtos.

Pressionamos "Enter" e, como estou usando o Git, ele apresenta uma mensagem com a opção adicionar esse arquivo ao Git. Vou marcar para não perguntar de novo e clicar no botão do canto inferior direito da mensagem para cancelar. Depois adicionarei o arquivo manualmente.

Essa implementação será bastante similar ao que vimos na nossa primeira Activity, que é a MainActivity.kt. Na linha 12 da MainActivity temos class MainActivity : ComponentActivity(){}. Então também aplicaremos isso na ProductActivity estendendo do ComponentActivity() vindo do (androidx.activity).

package br.com.alura.aluvery.ui.activities

import androidx.activity.ComponentActivity

class ProductActivity : ComponentActivity() {

}

Agora adicionaremos o construtor padrão para ele compilar. Para adicionarmos o conteúdo visual, usaremos o onCreate e, no menu de opções de importação, selecionaremos a que tem como sobrecarga apenas o Bundle.

Por fim, usaremos a opção que vem do Compose para adicionarmos os composables, codando setContent{} e, dentro dele, escrevendo o conteúdo visual da tela. Como esse será apenas um teste para sabermos se estamos acessando o conteúdo visual dessa tela, codaremos apenas um texto indicando que é nosso formulário de produtos.

Para isso utilizaremos os padrões que já estamos acostumados no Compose, como é o caso do tema AluveryTheme, do Surface e assim por diante. Então nosso código fica:

package br.com.alura.aluvery.ui.activities

import androidx.activity.ComponentActivity

class ProductActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstaceState)
        setContent {
            AluveryTheme {
                Surface {
                    Text(text = "Formulário de produto")
                }
            }
        }
    }

}

Temos um conteúdo inicial para testar. Caso queiram criar um preview, fiquem à vontade, mas neste momento nosso objetivo é chegar o mais rápido possível na execução para, logo em seguida, focarmos no design. Por isso não vou colocar o preview.

Antes de executarmos, aprendemos que, no Android, precisamos configurar o Manifesto para ele ser launch. Assim conseguiremos acessar essa tela quando executarmos o código.

Para acessarmos o Manifesto, pressionaremos "Ctrl. + Shift + N", para buscar arquivos. Pesquisaremos "Manifest" e abriremos o resultando AndroidManifest.xml.

Em seguida, acessaremos a linha 18 desse arquivo, onde está o <activity. A partir dessa linha configuraremos o acessaremos às activities, tanto para registrar o formulário, quanto para torná-lo launch.

Primeiramente alteraremos a linha 19, onde está a .MainActivity, porque mudamos o pacote e a alteração não foi refletida no manifesto. Portanto escreveremos android:name=".ui.activities.MainActivity". Nosso próximo passo é apagar o <intent-filter>, ou seja, da linha 23 à linha 27, para que a MainActivity não seja laucher.

Agora definiremos nossa nova Activity que criamos, que é a ProductFormActivity. Então codamos o name, indicando o caminho, e o exported, para nosso sistema conseguir chamar a activity. Por fim codamos o intent-filter, para que essa activity ser launch.

<activity android:name=".ui.activities.ProductFormActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Agora, ao executarmos nosso app, pressionando "Shift + F10", observamos esse resultado. Portanto temos nosso formulário pronto para começarmos a implementar a parte do design.

Sendo assim, a seguir focaremos em como chegar a um resultado próximo ao que vemos no Figma.

Implementando formulário dos produtos - Adicionando os campos do formulário

Nosso próximo passo é iniciar a implementação do nosso formulário, considerando layout e design. Para isso voltaremos ao Figma para observarmos o protótipo.

Então construiremos o layout com um título, indicando a criação de um produto, quatro campos de texto, que recebem as informações de "url", "nome", "preço" e "descrição" do produto, e um botão que indica uma ação de salvar. Todas essas informações estão em uma estrutura de coluna.

Criando o formulário no Android Studio

Para começarmos essa implementação, voltaremos para o Android Studio, acessaremos a Activity ProductFormActivity.kt. Nele construiremos uma estrutura mínima para adicionar cada um dos componentes.

Como agora precisaremos visualizar as alterações que fazemos no nosso código, criaremos o composable que representará a tela do nosso formulário e o seu preview.

Para isso, na linha 25, escreveremos comp para criamos o live template do novo @Composable. Chamaremos esse composable de ProductFormScreen(), como temos na MainScreen que é nossa Home.

//Código suprimido

@Composable
fun ProductFormScreen(){

}

Depois, na linha 31, escrevemos prev para criarmos o live template do @Preview chamado ProductFormScreenPreview(). Dentro do preview chamaremos o composable que criamos dentro do AluveryTheme, para observarmos como ele irá se comportar com o tema que criamos.

//Código suprimido
@Preview
@Composable
fun ProductFormScreenPreview() {
    AluveryTheme {
        Surface {
            ProductFormScreen()
        }
    }
}

Feito isso, podemos migrar todo o código que deixamos dentro do setContent, da linha 16, ou deixar o Surfice e chamar o ProductFormScreen() dentro dele. Faremos a segunda opção.

//Código suprimido

setContent {
    AluveryTheme {
        Surface {
            ProductFormScreen()
        }
    }
}

Assim temos nossa estrutura inicial para começarmos a fazer o código. Então começaremos construindo o layout em coluna dentro do ProductFormScreen(), codando Column{} na linha 29. A partir da Coluna, adicionaremos todos os elementos desejados.

No caso do título, escrevemos o Text(text = "Criando o produto") na linha 31, criando o título que está no nosso Figma. Em seguida precisamos dos quatro campos de texto, que codaremos com TextField(value = , onValueChange = ).

Como aprendemos, o TextField() segue o padrão de state hosting, onde precisamos passar o valor que queremos (value) e o que fazer na mudança desse valor (onValueChange). Nesse caso específico, para termos um formulário funcional, podemos criar os estados para esses campos.

Então para o primeiro campo codaremos var url by remember {} antes do TextField(), para usarmos a implementação de delegation. Dentro do remember, adicionaremos a função mutableStateOf(""), para informar que mudaremos o valor de uma String.

//Código suprimido

@Composable
fun ProductFormScreen(){
    Column {
        Text(text = "Criando o produto")
        var url by remember {
            mutableStateOf("")
        }
        TextField(value = , onValueChange = )
    }
}

Precisaremos fazer a importação de cada um dos by remember que codarmos, no caso será apenas o mutableStateOf, para o Compose conseguir adicionar o valor diretamente nas nossas variáveis. No caso será a url, que será um mutableStateOf(""), ele colocará o valor diretamente de String.

Portanto clicamos em remember, onde temos a marcação de erro, pressionamos "Alt + Enter" e selecionamos a opção de importação. Com isso ele faz o import, tanto para inserir, quanto para receber esse valor. Agora no TextField da, agora, linha 36, podemos passar o value = url e o onValueChange de mudança para termos o comportamento esperado.

//Código suprimido
        var url by remember {
            mutableStateOf("")
        }
        TextField(value = url, onValueChange = {
            url = it
        })

Portanto essa será a estrutura mínima para cada um dos nossos campos de texto. Sendo assim, podemos copiar e colar esse código para criar os demais campos mais rapidamente e, assim, seguirmos para última parte, que é a criação do botão.

//Código suprimido

@Composable
fun ProductFormScreen(){
    Column {
        Text(text = "Criando o produto")
        var url by remember {
            mutableStateOf("")
        }
        TextField(value = url, onValueChange = {
            url = it
        })
        var name by remember {
            mutableStateOf("")
        }
        TextField(value = name, onValueChange = {
            name = it
        })
        var price by remember {
            mutableStateOf("")
        }
        TextField(value = price, onValueChange = {
            price = it
        })
        var description by remember {
            mutableStateOf("")
        }
        TextField(value = description, onValueChange = {
            description = it
        })
    }
}

Atenção: Cada vez que copiarem e colarem o código, atentem-se para evitarem inconsistências, como não mudar o nome das variáveis ou o valor inicial e de mudança nos campos de texto.

Temos nossos campos mas, ao abrirmos o preview para observarmos o que aconteceu, meu preview apresentou um erro. Provavelmente foi algum bug do Android Studio que não deixou tão claro para ele.

Sendo assim, adicionaremos os demais campos e, caso ainda assim não funcione, eu limparei nosso projeto e farei o build novamente para analisarmos se o preview aparecerá. No nosso projeto falta apenas o botão, e usaremos o composable Button() para adicioná-lo ao nosso Compose.

Codamos Button(onClick = { /*TODO*/ }) {} a partir da linha 60 e, assim, reparamos que esse composable tem o parâmetro onClick. Essa é uma expressão lambda para definirmos o que queremos fazer durante a ação de clique. Além disso, dentro dele temos um espaço, entre as chaves vazias {} para adicionarmos o texto, então codaremos Text(text = "Salvar").

//Código suprimido

    Button(onClick = { /*TODO*/ }) {
        Text(text = "Salvar")
    }

Ajustando o problema do preview

Como antes, meu preview continua sem funcionar, então eu vou limpar o projeto. Para limparmos o projeto, podemos usar o atalho "Ctrl + Shift + A" e aparecerá a possibilidade para buscarmos por uma ação. Procurando por "Clean", surge a opção "Clean Project". Vamos selecioná-la e pressionar "Enter" e, com isso, a limpeza do projeto começará.

Quando a limpeza termina, refaremos o build, pressionando "Ctrl + F9" ou clicando no botão com ícone do martelo verde, na barra de ações da parte superior do Android Studio. O build é um processo um pouco demorado e, quando ele finaliza, conseguimos observar o preview da estrutura inicial do nosso código.

No preview vemos a estrutura mínima do nosso formulário. Neste momento não ajustaremos para ficar com o mesmo design que temos no protótipo do Figma, apenas construiremos a estrutura e verificar se ela funciona como esperado.

Sendo assim, pressionamos "Shift + F10" para executar o app. Com isso, observamos que já temos a estrutura de coluna com o título, os quatro campos de texto e o botão. Ao clicarmos em um dos campos, notamos que conseguimos adicionar os textos, porque criamos os vínculos com os estados, e reparamos que cada estado é separado, ou seja, nenhum interfere no outro.

Abaixo dos campos temos o botão "Salvar" alinhado à esquerda com a cor do tema. Nele conseguimos fazer a ação de clicar, como reparamos pelo efeito chamado ripple, que é um efeito de ondulação no local clicado.

Então nosso objetivo nesse momento era o de criar essa estrutura. A seguir focaremos em como chegar mais próximo do design do formulário apresentado no Figma.

Sobre o curso Jetpack Compose: formulário e gerenciamento de estado

O curso Jetpack Compose: formulário e gerenciamento de estado possui 183 minutos de vídeos, em um total de 58 atividades. Gostou? Conheça nossos outros cursos de Android em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Android acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas