Alura > Cursos de Mobile > Cursos de Flutter > Conteúdos de Flutter > Primeiras aulas do curso Flutter: Controller, navegação e estados

Flutter: Controller, navegação e estados

Construindo formulários - Apresentação

Bem-vinda e bem-vindo ao nosso novo curso de Flutter. Neste curso de Flutter, vamos dar continuação no nosso projeto de tarefas gamificadas. Antes de falar quais são os temas que veremos, quero mostrar para vocês o nosso aplicativo.

Temos o nosso aplicativo com as nossas tarefas que construímos no último curso, só que agora temos uma nova funcionalidade: podemos adicionar uma nova tarefa.

Vou colocar que temos uma nova tarefa, “Derrotar o Dash Vader”. Vou definir a dificuldade “5” e já tenho uma imagem salva, do Dash, o mascote do Flutter, vestido de Darth Vader.

Vou clicar em “Adicionar”, ele vai informar que está criando uma nova tarefa e assim ela vai aparecer na nossa lista de tarefas. Podemos interagir com ela como podemos interagir com todas as outras tarefas.

Para fazer tudo isso, temos que ver alguns novos conceitos, como conceitos de formulário, e de como funciona um formulário, o que é um TextFormField, TextField, o que é Controller etc.

Também aprenderemos algumas coisas sobre errorBuilder da imagem, para ela não ficar estranha se não estiver carregada, e depois vamos começar a falar sobre validações no formulário, algumas diferenças de teclado para cada formulário.

Depois, vamos começar a aprender sobre navegações, entender o que é uma navegação no Flutter, o que significa navegações e rotas, quais são os tipos de navegações e quais vamos usar.

Depois, vamos ter uma conversa entre widgets, para entender como os widgets trocam informações entre si, e começar a explorar o mundo dos estados, começar a entender o que é um estado e como podemos controlá-lo.

Por fim, finalizamos o nosso projeto falando sobre bugs e como lidar com eles. Depois disso tudo, teremos o nosso aplicativo, como vocês viram neste vídeo.

Está animado? Eu estou completamente animado para dar essa aula para vocês. Vamos lá?

Construindo formulários - Como será nosso formulário?

Quer dizer, então, que você já viu a apresentação desse curso e já sabe como as coisas vão funcionar? Ótimo, mas precisamos ter um pouco mais de detalhe sobre o que vamos construir.

Primeiro, vamos fazer as coisas que já sabemos fazer. Vamos dar uma olhada na nossa tela de formulário, que é a nova tela que vamos ter que criar no nosso projeto.

Na nossa tela de formulário, conseguimos ver que já tem um app bar, uma barra superior, com as palavras “Nova Tarefa”. Isso já sabemos fazer. Também tem uma seta que nunca mexemos antes, mas não precisa se preocupar agora com ela.

Temos a app bar e temos o body do nosso Scaffold, ou seja, isso tudo é um scaffold. Já sabemos como funciona o scaffold, já usamos esse widget.

O body do scaffold é branco, o contêiner branco, mas dentro dele parece que tem um contêiner cinza, e ele tem uma borda, nunca mexemos com bordas, coisa nova, bordas pintadas.

Esse contêiner cinza tem alguns elementos aqui dentro, o elemento “Nome”, “Dificuldade” e “Imagem”, embaixo. Falei a palavra “embaixo”, o que significa que está tudo dentro de uma column.

Temos uma column com os filhos “Nome”, “Dificuldade”, “Imagem”. Essa imagem que, na verdade, é um contêiner azul com borda arredondada, que já sabemos fazer, com uma imagem dentro, que é tipo uma câmera riscada, ou seja, indicando que não há fotos.

Embaixo dessa imagem, temos o botão “Adicionar”. Já sabemos fazer um botão, então já sabemos fazer essa tela. O que não sabemos são esses “Nome”, “Dificuldade” e “Imagem”. Se eu clicar nele, vocês vão ver que é um campo de texto, nunca mexemos com campos de textos. Uma coisa de cada vez.

Quando clico no campo de texto, ele abre o teclado para eu poder digitar. Aqui, em “Dificuldade”, ele abre outro campo de texto só de número. Na “Imagem”, posso colar uma URL e ele carrega automaticamente uma imagem no contêiner azul.

E, por fim, o botão “Adicionar”, onde adicionamos a nossa tarefa. Não vou adicionar, vai ficar um negócio estranho, e não precisamos ver isso agora, mas a ideia é que vamos ver o layout, o front-end do nosso projeto.

Já entendemos um pouco, temos que fazer o scaffold, vai ter um contêiner cinza com três elementos em coluna, uma parte de imagem e um botão. Vamos começar por aí?

Agora vamos abrir o nosso projeto, que vai estar disponível para vocês baixarem, caso não tenham feito no último curso. No nosso projeto inicial, vamos criar uma nova tela.

Primeira coisa, vamos criar um novo documento dentro da nossa pasta “screens”. Dentro do nosso “Project”, à esquerda, vamos entrar na pasta “lib”, que vai ter duas pastas: “components” e “screens”. Vamos entrar na pasta “screens”, clicar com o botão direito, e no começo do menu selecionar “New > Dart File”.

Vou chamar isso de “form_screen”, “tela de formulário”. Nesse arquivo vou adicionar um novo widget, vou criar um StatefulWidget, e o nome dele vai ser class FormScreen extends StatefulWidget.

Temos que adicionar o nosso material app, clicamos em StatefulWidget, “Alt + Enter”, “Import library ‘package:flutter/material.dart’”. Agora que já temos o material importado, já temos a nossa tela.

Mas precisamos começar a visualizar como a nossa tela está mudando. Vou no “main.dart”, em que temos um home, o InitialScreen(), que criamos no curso anterior.

Criamos essa tela toda que estamos vendo com as nossas tarefas. Não quero vê-la agora, quero ver o FormScreen que estou criando. Então, vou retirar InitialScreen e vou escrever FormScreen. Cuidado que existem outros widgets com nomes parecidos, como FormState e FormFieldState, tem que ser o que acabamos de criar, FormScreen.

Ele vai importar automaticamente do nosso projeto, vai parar de usar o InitialScreen, vai ficar cinza. Não vou tirar agora, porque mais tarde vamos voltar com ele. Conferimos se está funcionando, vou dar um hot reload para ele mudar de tela para nós.

A tela está toda preta, por quê? Porque temos o StatefulWidget que retorna um contêiner, mais nada, e não é isso que queremos. Temos que criar a nossa tela do jeito que vimos, com scaffold e etc.

Então, vamos substituir esse Container() por um Scaffold. Esse Scaffold precisa do quê? Precisa do parâmetro appBar, e esse parâmetro precisa do appBarWidget.

Lembrando que o widget é esse mais amarelado, com sinal de igual. No appBar, podemos colocar um title, que fizemos antes, esse title vou colocar que é uma title: const Text('NovaTarefa'). Vou dar uma hot reload rapidamente.

Temos a nossa “Nova Tarefa”, está bonito do jeito que tínhamos visto antes, agora precisamos colocar os elementos no centro, no body. O body fica dentro do appBar? Não, fica dentro do Scaffold, é outro parâmetro.

Então, body. Nesse body, vamos começar a brincar um pouco. Vou criar um body: Container e vou falar que esse Container tem uma cor, color:Colors.black12, um cinza quase branco.

Quero que esse Container tenha um height:650. Esqueci de colocar a vírgula depois do Colors.black12,, ele já brigou comigo. Vou dar um “Ctrl + Alt + L” para indentar, arrumei, coloquei a vírgula.

Coloquei o height, coloquei o width, o width: 375. Não estou tirando isso do nada, é a partir do design que fizemos no passado. Algumas vezes vamos ter que experimentar, mas, no meu caso, já deixei tudo pronto, então não vou ficar adivinhando valores.

Criei o nosso Container, o que acontece se eu der um hot reload? Ele criou um contêiner mais cinza que não encaixou na tela toda e está mais à esquerda. Vou dar uma mudada na cor dele, vai ser completamente preto.

Esse é o nosso contêiner, não está legal, eu quero que ele esteja no centro e esteja centralizado no body. Como posso fazer isso? Vou voltar para o nosso color: Colors.black12, dar um hot reload e mostrar para vocês um novo widget agora.

Vou dar um wrap no contêiner, “Alt + Enter”, “Wrap with widget”, só que vou dar um wrap com um widget que nunca vimos, que é o “Wrap with Center”.

Esse “Center” centraliza o nosso widget dentro do parente dele. Então, coloquei um “Center” em volta do contêiner, vou dar um hot reload. Agora o nosso contêiner está bem no centro.

É mais difícil de ver porque está no colors: Colors.black12, vou colocar no color: Colors.black só para vocês verem, mas a ideia é que usemos o color: Colors.black12 no nosso container, porque é a cor do container que vimos no começo da aula.

Então, está no centro, só que ainda não parece muito com o que queríamos. O que queríamos? Ele meio arredondado, com uma borda. Isso significa que vamos ter que decorar o nosso container. Já o decoramos antes, certo?

decoration: BoxDecoration(). Temos que tomar cuidado porque o Colors tem que estar dentro do BoxDecoration, senão vai dar problema. Então, vou tirar o Colors de dentro do contêiner e colocá-lo no BoxDecoration.

Algumas outras que queremos colocar no nosso decoration, queremos que ele tenha uma borda circular, que já aprendemos a fazer. Então, borderRadius: BorderRadius.circular(10).

Vou dar um hot reload e agora já está mais circular a nossa borda, mas não acabou aí, ele tem uma borda visível, uma borda preta em volta. Como fazemos isso? Adicionamos um novo parâmetro chamado border.

Esse border precisa de um widget chamado Border. Eu preciso de uma borda que englobe todo o nosso widget, então border: Border.all, e o tamanho da borda, border: Border.all(width: 3), vou colocar o tamanho de 3, que é o tamanho da borda que quero no nosso contêiner.

Agora o nosso container tem uma borda e está começando a criar beleza na nossa nova tela, mas não é só isso. O que tínhamos também? Tínhamos que definir que o nosso body era uma column com vários filhos, e dentro desses filhos iria ter uns widgets que nunca mexemos.

Então, só para finalizar o nosso Container, vou colocar que ele tem, depois de BoxDecoration, child: Column(), que vai ter children: [], que vão ser os elementos dentro do nosso contêiner cinza.

Mas só vamos continuar a ver isso agora no próximo vídeo.

Construindo formulários - TextField ou TextFormField?

Foi exatamente aqui que paramos. Fizemos o nosso scaffold com app bar de “Nova Tarefa”, e o body com container cinza com uma borda bonita. Agora temos que começar a mudar as partes que vão receber as nossas informações.

Precisamos criar um novo elemento em que podemos clicar e digitar dentro dele, o que vimos no formulário na aula anterior. Precisamos de um widget que seja como um texto, mas um campo de texto.

Como fazemos para achar um widget como esse? Para isso, vamos na documentação que nos ajuda bastante nisso. Vou no “flutter.dev” e, na parte superior direita, temos três traços na horizontal que são o ícone de menu.

No menu, você vai ver que tem várias opções, sendo a última delas, na parte inferior, a opção “Docs”. Vamos clicar em “Docs” e, no final da lista que se abre abaixo, você tem uma opção chamada “Cookbook” que é o nosso livro de receitas do Flutter que vai nos ajudar muito.

No “Cookbook”, veremos que tem vários tópicos, como “Animação”, “Design”, “Efeitos”, “Formulários” etc. "Formulários", não é isso que estamos criando? Então vamos ler. O “Formulário” tem, na segunda opção, “Criar e estilizar um campo de texto”.

“Text Field”, “campo de texto”, não é isso que estamos procurando? É isso que estamos procurando, então vamos lá. No “Textfield”, se você quiser parar e dar uma lida com calma no tutorial, não tem problema, ele é bem curto.

Ele fala que temos dois tipos de widgets para campo de texto: o TextField e o TextFormField. Qual seria a grande diferença entre eles? Vou mostrar para vocês sem ficar lendo a documentação. Vocês são livres para ler a documentação, porque quero mostrar na prática qual é a diferença.

Vou voltar no nosso projeto e, na coluna que criamos, vou colocar o TextField() e dar um hot reload. Apareceu no nosso aplicativo tipo uma linha. O que acontece se eu clicar nessa área? Ele vai abrir o nosso campo de texto para podermos digitar, então já é um campo de texto, posso digitar o que eu quiser.

Então, já posso digitar o que eu quiser, já é um campo de texto. E qual seria a grande diferença entre o TextField e o TextFormField? Vou vir e criar o TextFormField(), logo embaixo do TextField(). Lembrando que eles estão dentro de uma Column, então um vai estar embaixo do outro.

Vou dar um hot reload para podermos ver o TextFormField() e apareceu outro campo de texto aqui embaixo. Posso vir nele e digitar a mesma coisa, não mudou nada, os dois são iguais.

Então, qual a diferença entre um e outro? A diferença não é superficial. Na superfície, os dois são bem parecidos, mas o TextFormField tem um parâmetro diferente.

Podemos pegar, na documentação do TextField, ou podemos colocar o mouse em cima de TextField. Dentro dele, você vai ver que tem vários parâmetros.

Eu sei que isso é para quem tem o olho mais treinado, mas é importante que vocês tenham essa curiosidade quando virem dois widgets extremamente parecidos e deem uma olhada em cada um deles.

O TextField tem controller, tem decoration, tem várias funções e parâmetros, como a função onChanged, que é quando a informação muda o que ele deve fazer. Tem muitas coisas, vocês podem parar e olhar, não vou fazer isso, quero que demos uma olhada no parâmetro que diferencia o TextField do TextFormField.

Aqui, parei no onChanged de propósito. Vamos no TextFormField e vamos procurar o onChanged. Vou colocar o mouse em cima de TextFormField e ele vai nos mostrar os parâmetros, os mesmos parâmetros de TextField, só um a mais.

Alguns são a mais, mas esse é o mais detalhado. Achei o onChanged. Embaixo dele, temos alguns outros, onTap, onSaved, e validator. O TextFormField tem um parâmetro que o TextField não tem, que se chama “validação”.

Temos a habilidade de validar a informação que entra no campo de texto. Qual seria a vantagem de validar? Vamos supor que você cria um campo de texto que só recebe números de telefone.

Você quer que a pessoa coloque números de telefone nesse campo de texto e ela coloca o nome completo dela. Isso seria um grande problema, porque números são diferentes de textos. Às vezes, você quer manipular números de um jeito e você não pode fazer da mesma forma com textos.

Não vale a pena você deixar o seu usuário colocar letras no lugar de números, você precisa validar essa informação, ter certeza de que a informação é a que você está pedindo. Isso dá um grande poder para o TextFormField.

Além de que, quando você tem vários TextFormField juntos dentro de um widget chamado Form, ele vai procurar a validação de todos os TextFormField antes de permitir que você crie o objeto que você deseja.

Olha só, isso já é muito bom para nós, queremos criar uma tarefa que precisa de “Nome”, de “Dificuldade” e de “Imagem”, então precisamos validar se o “Nome” é um nome, se a “Dificuldade” é uma dificuldade e se a “Imagem” é uma imagem antes de criarmos essa nova tarefa.

Vamos usar validator, então para nós vale a pena usarmos TextFormField. Não vamos usar o TextField, vamos usar o TextFormField.

O que quero fazer aqui? Quero deixar o TextFormField bonito. Primeiramente, quero mexer em alguns parâmetros dele para entendermos como ele funciona.

Vou dar hot reload, quero deixar o TextFormField bonito, e para isso vamos usar um parâmetro que ele tem e que já conhecemos, que é o decoration. Só que o decoration do TextFormField precisa de um tipo diferente de widget que é o InputDecoration.

Vou em InputDecoration e, dentro dele, podemos colocar as adequações que desejamos, como, por exemplo, uma borda, border que precisa de um widget específico quando está dentro do InputDecoration que é o border: OutlineInpurBorder(). Ele terá uma borda dizendo qual é o tamanho dele.

Quero também que ele tenha um texto de dica, ou seja, quero olhar e saber qual é esse campo de texto, então vou escrever hintText que pede uma string. Falamos que o hintText: 'Nome'. Se eu der um hot reload, vai aparecer “Nome”.

Tem mais uma coisa que quero também, quero que a cor de dentro do TextFormField seja diferente, que tenha um branco diferente. Vou usar o fillColor que é a cor que preenche o nosso TextFormField.

Vou colocar que essa cor é fillColor: Colors.white70, não qualquer white, porque white completo dói o olho, então white70. Vou dar hot reload e nada mudou porque precisamos de mais um parâmetro do nosso InputDecoration que é o filled, se ele está preenchido ou não.

Vou colocar filled: true. Quando coloco true, ele permite que a cor de preenchimento seja mostrada. Então, tem esses detalhes que é legal pararmos e darmos uma analisada. Podemos colocar o mouse por cima e vermos o que ele pede, quais são os parâmetros, é muita coisa, mas, quanto mais você entende, mais você consegue manipular.

Já temos o nosso TextFormField que tem uma borda bonita. Tem outros detalhes também, eu quero que o nome não esteja à esquerda, mas centralizado. Como fazemos isso? No próprio TextFormField, temos um parâmetro chamado textAlign.

Posso colocar textAlign: TextAlign.center, ele vai ficar no centro, do jeito que quero. Para deixar um pouco mais bonito, vou envolver esse TextFormField com um padding para ele ter espaçamento, senão fica um pouco estranho.

Vou na linha 28, pressiono “Alt + Enter” no TextFormField, “Wrap with Padding”. Ele já vai deixar o nosso TextFormField com um padding, com uma borda.

Agora conseguimos escrever a nossa informação, posso vir no campo "Nome" do aplicativo e escrever o nome da ação que quero fazer, “Assistir Star Wars”. Essa informação não está sendo usada, não está sendo armazenada, não está vindo para o nosso projeto, está flutuando, ninguém faz nada com ela.

Para isso, precisamos de um parâmetro específico do TextFormField, e do TextField também, chamado controller que é responsável por controlar a informação que está dentro do nosso campo de texto.

Temos o nosso controller, e como ele funciona? É isso que quero mostrar para você daqui a pouco.

Sobre o curso Flutter: Controller, navegação e estados

O curso Flutter: Controller, navegação e estados possui 196 minutos de vídeos, em um total de 46 atividades. Gostou? Conheça nossos outros cursos de Flutter 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 Flutter acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri powered by ChatGPT

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas