Iniciando um aplicativo com Flutter parte 2

Tecnologia

Anteriormente vocês viram uma introdução sobre iniciando com Flutter, algumas características, um pouco sobre widgets e estrutura de pastas (caso vocês não tenham visto, podem ver aqui parte 1), e agora iremos continuar de onde paramos! Vamos olhar novamente a tela do artigo anterior:

Esta tela é um simples contador que vai sendo incrementado conforme for pressionando o botão, mas não iremos utilizar este exemplo, vamos começar do começo, portanto vamos no código e vamos apagar tudo, mas… que código??

Abra o arquivo main.dart que está na pasta lib, vocês verão um código parecido com este:

Agora sim podemos apagar tudo, exceto o import, a função void main e a classe MyApp, ficando igual a imagem a seguir: 

Agora vamos entender melhor o que cada parte faz:

  • import: É utilizado para importar dependências para aquele arquivo, neste caso estamos importando o package material do próprio Flutter para utilizar widgets focados em desenvolvimento android (mais à frente veremos como lidar com android e iOS separadamente).
  • main: É uma função comum em muitas linguagens de programação e como diz o próprio nome, ela é a função principal, que irá iniciar a nossa aplicação.
  • runApp: É a função que irá de fato rodar nossa aplicação, passando como parâmetro o widget raiz do aplicativo.
  • MyApp: é a classe raiz da aplicação.
  • build: É a função padrão de toda classe para renderizar (construir) algo na tela.

TIRA ESTADO, PÕE ESTADO

Depois de entendermos melhor sobre algumas propriedades, vamos falar um pouco sobre estado (state) de uma aplicação. Estado é literalmente o comportamento atual da aplicação. Como Flutter é reativo, qualquer alteração no estado que for escutada pela aplicação ativará uma re-renderização da mesma.

E com isso, existem dois principais tipos de widgets: widgets COM estado (stateful widgets) e widgets SEM estado (stateless widgets). Mas o que isso implica na prática?? Vamos lá:

Pegando o mesmo exemplo utilizado acima:

Não sei se repararam antes, mas a classe MyApp estende StatelessWidget!, e portanto, não existe estado nela, o que quer dizer que as informações que receber ou já estiverem ali, não serão modificadas. Stateless widgets são úteis quando não há necessidade de alterar quaisquer propriedades da página, como uma label, um texto, uma lista, etc, sendo que tudo que precisa ser feito é mostrar informações na tela do jeito que estiverem, sem possibilidade de modificações.

Por outro lado, temos os stateful widgets! Aqui vai um exemplo:

Vamos entender por partes, calma. Existem duas classes para cada stateful widget, a primeira (HomePage) estende diretamente StatefulWidget, e é ela que é responsável por criar o estado desse widget, utilizando a função createState() que retorna a outra classe essencial (_HomePageState). Esta classe, por sua vez, estende o estado do tipo HomePage (State<HomePage>), para que assim seja possível alterar o estado deste widget!

DicaEz: Vários editores possuem atalhos para se criar widgets!, o VSCode por exemplo, se tiver instalado o Flutter todo certinho no editor, vocês podem digitar stless (para criar um widget sem estado) e stful (para criar um widget com estado) e pressionar a tecla ‘Enter’, e tadãm! widget criado!

Vocês devem estar se perguntando “Mas como alterar o estado então??” Bom, esta pergunta será respondida jajá, por enquanto vamos finalmente começar nossa Amazing Todo-list!!!

O BOM PROGRAMADOR AO APP RETORNA

Para começar, vamos incrementar a classe MyApp como a imagem a seguir:

Como vamos trabalhar primeiramente com design de aplicativos Android (Material Design), nossa aplicação vai ser estar baseada no widget MaterialApp, que nos permite criar um aplicativo no estilo Material. Este widget tem várias propriedades, mas por hora iremos introduzir um título (title) que será uma identificação para nossa aplicação, e uma tela principal (home) que dirá para a aplicação qual é a página inicial.

Provavelmente vocês terão um erro relacionado a HomePage(), pois este widget não existe ainda, e por isso vamos resolver isso criando um stateful widget com o nome HomePage (ou o nome que preferir):

Na imagem acima, foi adicionado um Container (similar a uma div no html) onde seu filho (child) é um Text, com o texto “HOME PAGE”, mas… o que isso quer dizer? O que é o filho, ou filhos, de um widget?? Pois bem, filho, ou filhos, nada mais são do que widgets que estão abaixo ao widget pai na árvore de widgets, onde agregarão ao pai com alguma propriedade. No caso da imagem acima, o Container tem como filho o Text, então o texto gerado será agregado ao Container! Ainda estão confusos? Vamos à outro exemplo. Digamos que vocês precisam fazer um botão, e dentro dele precisa ter um texto escrito “Entrar”, como o fariam em Flutter? (Podem utilizar o widget FlatButton para o botão). A resposta:

Espero que tenha ficado um pouco mais claro o uso de child pelos widgets, mas mesmo que ainda tenham dúvidas e não esteja muito claro, continuem caminhando ao meu lado que tenho certeza que irão aprender muito! (Obs: a propriedade onPressed foi colocada no exemplo pois é uma propriedade obrigatória de botões).

RETORNANDO À LISTA!

Agora vamos rodar o código inicial (o que utiliza Container e Text) e analisar o resultado:

Se as telas estiverem parecidas com a imagem acima, estamos indo bem! Se não, dêem uma olhada novamente acima, desinstalem a aplicação do dispositivo e rodem novamente a aplicação, e qualquer coisa tem os comentários aí!

Bom, tá meio estranho né? Não tem fundo nem nada.. parece até sem estrutura alguma! Pois bem, realmente está sem nenhuma estrutura, mas.., por que não adicionarmos uma estrutura então? Vamos incrementar nosso código da HomePage:

Como podem reparar, foi adicionado um widget que envolveu o Container anterior, chamado de Scaffold. Scaffold é andaime em inglês, o que diz muito sobre este widget, pois ele é o que vai sustentar, o que vai dar uma estrutura inicial ao nosso aplicativo!

Powered by Rock Convert

O Scaffold, como qualquer outro widget, tem uma gama enorme de propriedades que podem ser utilizadas, mas por enquanto iremos simplesmente adicionar uma appBar e um body.

A propriedade appBar recebe um widget AppBar, que cria uma barra no topo da nossa aplicação, onde também existem várias propriedades, mas por hora vamos só adicionar um título.

Já a propriedade body recebe um widget que será o conteúdo em si da página, no caso um Container com um Text.

Se ainda não rodaram a aplicação, a hora é agora! Vocês verão algo assim:

Agora está parecendo mais um aplicativo! Mas não vamos parar por aqui!! Vamos moldar ainda mais nossa Amazing Todo List!

COLOCANDO ALGUNS DADOS

Primeiramente, vamos criar uma lista com alguns objetos que irão compor nossa todo list:

Como podem ver, foi criado uma lista (array) com alguns objetos, e estes por sua vez com algumas propriedades, sendo elas: a identificação (id), o título (title), e se está checado ou não (isChecked). 

Depois disso, vamos criar a lista propriamente dita, e nada melhor do que utilizarmos o widget ListView para isso:

Foi alterado o body do Scaffold para um widget ListView, mas vamos utilizar um método específico deste widget, o builder, que nos permite renderizar itens em uma lista dinamicamente.

A propriedade itemBuilder é obrigatória, e a função dela nada mais é do que renderizar cada item, iterando pela quantidade estabelecida que é informada na propriedade itemCount. Apesar de já existir uma função na propriedade itemBuilder, ela não foi construída ainda, então vamos construí-la!

DEIXANDO COM CARA DE LISTA!

Como a propriedade itemBuilder requisita um widget para ser renderizado, nossa função vai ser do tipo Widget, e ela vai receber como parâmetro o contexto (context) e o índice (index) de cada item.

Para criar uma lista com um texto e um botão de checar na mesma linha precisamos pensar em como isso é constituído. É um embaixo do outro? Se sim, seria utilizado o widget Column (coluna). É um ao lado do outro? Neste caso seria utilizado o widget Row (linha). No nosso caso então utilizaremos o widget Row para atingir nosso objetivo. 

Row por sua vez possui várias propriedades, onde iremos utilizar duas delas, a mainAxisAlignment, que alinha os filhos no eixo principal, e como é uma linha, o eixo principal é horizontal e portanto irá alinhar horizontalmente conforme o especificado, e além disso, iremos alinhar com o tipo MainAxisAlignment.spaceBetween, para que, como o próprio nome já diz, alinhe os filhos deixando um espaço entre eles. A outra propriedade que iremos utilizar é a children (filhos), que nos permite colocar quantos widgets quisermos como filhos do Row, para que assim fiquem em linha.

Como estamos criando uma todo list, o básico dela é mostrar de um lado o texto e do outro uma forma de checar se está feito ou não a atividade. Pois bem, como filhos do Row então teremos um texto (Text) e uma checagem (CheckBox).

Na parte do texto, além do widget Text que já conhecemos, vamos utilizar outro widget para dar um espaço no texto, assim ele não irá ficar colado com a tela, e este widget é o Padding! O Padding tem como propriedade obrigatória o padding, que é onde colocaremos o tamanho que queremos do mesmo, utilizando a classe EdgeInsets, mais especificamente EdgeInsets.all para inserir em todos os lados (poderia ser somente a esquerda ou o lado que fosse necessário), e daí sim, como filho do Padding, colocaremos o Text.

FAZENDO A CHECAGEM!

Agora, para a parte de checagem, utilizaremos o CheckBox como já foi dito anteriormente, onde o mesmo tem a propriedade obrigatória onChanged, que recebe uma função que irá retornar o novo valor a ser armazenado quando tocar em checar, e também vamos indicar qual o valor atual do CheckBox com a propriedade value.

Sei que querem rodar logo essa aplicação para ver como está, mas só mais uma ou duas coisinhas e já poderemos botar pra rodar! Primeira coisa é que os textos e o valor do CheckBox estão sendo pegos a partir da nossa lista criada anteriormente (data). E a segunda coisa é que precisamos implementar a função que irá alterar o valor da propriedade isChecked dos itens da nossa lista! Bora lá!!

Como é uma função que não retorna nada, vai ser do tipo void e irá receber o novo valor e o índice do item que estamos alterando como parâmetros, e para alterar não tem segredo, vamos pegar o item do data a partir do índice (index) e vamos alterar a propriedade isChecked, definindo seu valor como o novo valor (newValue).

Bom, se rodarem este código e clicarem em algum botão para checar, vão perceber que nada está acontecendo, mas por quê? Pois bem, não adianta alterarmos o valor de alguma variável se não informarmos para a aplicação que ela precisa re-renderizar!! Mas calma, não fiquem bravos ou chateados porque vai vir mais falação e código e explicação e blá blá blá, só precisamos colocar o que queremos modificar dentro de uma funçãozinha!! setState():

Como podem ver acima, basta colocar setState e bora rodar novamente!! Vocês vão ter algo assim:

E é isto por enquanto, muito obrigado por terem lido até aqui, espero ter ajudado a entenderem um pouco melhor como funciona desenvolver aplicações em Flutter, mas saibam que não para por aqui!! Vamos evoluir nossa Amazing Todo List, para que fique realmente Amazing!! Fiquem de olho!!

DicaEz: Se quiserem olhar o projeto, aqui está um link para o mesmo no Github: https://github.com/RickMartian/amazing_todo_list.