Por que eu devo ler este artigo:Criar UIs ou interfaces de usuário bonitas e que facilitem a experiência do usuário parece ser uma tarefa difícil. O framework Flutter torna essa tarefa mais fácil e intuitiva com a utilização dos Widgets, mesmo para alguém que não é um designer.

O Flutter foi concebido para criação de UI ou interfaces de usuário para aplicativos. Uma UI é construída em Flutter com base em Widgets, que são semelhantes aos Components utilizados em tecnologias como React.


Guia do artigo:

Um Widget gera uma parte da UI do aplicativo. Por exemplo: um texto, uma imagem ou um botão são criados a partir de um Widget.

StatelessWidget e StatefulWidget

Um aplicativo pode responder a eventos como um clique em um botão e alterar a visualização de seus componentes. Em Flutter para que isso aconteça é preciso mudar o estado de um Widget.

O Widget descreve como uma parte da UI deve ser visualizada, com base em sua configuração e estado atual. O estado é uma informação que é lida quando um Widget é construído. Essa informação pode ser como uma string ou um número, que quando muda também produz mudanças nas características de um Widget.

Com relação a mudança de estado os Widgets podem ser StatelessWidget e StatefulWidget:

  • StatelessWidget define Widgets que não mudam suas características com a mudança de estado. Um StatelessWidget não possui um estado que mude, pois é o Widget que mantém as mesmas características desde o início da execução do app.
  • StatefulWidget define Widgets que mudam suas características com a mudança de estado, ou seja, tem um estado mutável. Durante a execução do app, se a informação do estado mudar, isso será refletido no Widget.

    Por exemplo, em um aplicativo ao clicar em um botão que é um StatefulWidget, um número é incrementado. O valor do número é uma informação ou estado que mudou e isso se refletiu no Widget Text que exibe o valor do número no aplicativo, conforme a Animação 1.

    Exemplo de mudança de estado de um Widget com um contador
    Animação 1. Exemplo de mudança de estado de um Widget com um contador

    Nesse artigo vamos abordar apenas esses dois tipos de Widgets no contexto do estado.

    Widgets com filhos

    Cada Widget pode ter um ou mais Widgets filhos. Criamos um com child, e para uma coleção de filhos usamos children. Veja um trecho de código onde declaramos um Widget filho com child, conforme a Listagem 1.

     Center(
      child: Text(
    
    Listagem 1. Declaração de umWidget filho com child

    Explicando o código:

    • Linha1: Declaração de um Widget Center
    • Linha 2: Declaração de um Widget filho com child. Esse Widget é um Text.

    Agora temos outro trecho de código com a declaração de uma coleção de Widgets filhos com children, conforme a Listagem 2.

        Row(
            children: [
               Icon(Icons.star, color: Colors.green[500]),
               Icon(Icons.star, color: Colors.green[500]),
               Icon(Icons.star, color: Colors.green[500]),
            ],
           )
    
    Listagem 2. Declaração de uma coleção de Widgets filhos com children

    Explicando o código:

    • Linha 1: Declaração de um Widget Row
    • Linha 2: Declaração de uma coleção de Widgets filhos com children
    • Linhas 3 a 5: Widgets Icons compõem a coleção de Widgets filhos

    Método build

    Os Widgets são criados em um app através do método build, que contém um parâmetro BuildContext. Ele define a posição e características dos Widgets no layout do aplicativo.

    No trecho de código a seguir temos o método build, conforme a Listagem 3.

        Widget build(BuildContext context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(
                  title: const Text('Home'),
                ),
              ),
            );
    
    Listagem 3. Trecho de código de um app utilizando o método build para criar os widgets

    Explicando o código:

    • Linha 1: Método build que cria os Widgets no app
    • Linha 2: MaterialApp é o Widget principal
    • Linha 3: A página home do app tem como Widget principal Scaffold. Esse define um layout básico de acordo com o Material Design.
    • Linha 4: Widget AppBar, que será a barra superior do aplicativo, é um dos componentes do layout básico do Scaffold
    • Linha 5: propriedade title da AppBar para definir o título que será exibido na barra do app.

    Vamos acompanhar alguns exemplos simples de apps feitos com Flutter.

    Nos códigos de exemplo vamos utilizar a biblioteca flutter/material.dart para criar aplicativos de acordo com o Material Design, a linguagem de design criada pelo Google.

    Exemplo de App com StatelessWidget

    Nesse exemplo vamos usar o MaterialApp, que é um Widget de conveniência que agrupa outros widgets em um app que utiliza o Material Design.

    Ao utilizar o MaterialApp podemos também usar o Widget Scaffold, que define um layout básico de acordo com o Material Design. Ele abrigará outros Widgets como AppBar, Container, Text e outros.

    No código da Listagem 4 vamos criar um app com StatelessWidget, ou seja, os Widgets não sofrerão mudança durante a utilização do app.

     import 'package:flutter/material.dart';
      
       void main() => runApp(const MeuApp()); 
      
       class MeuApp extends StatelessWidget {
           const MeuApp(); 
           @override
           Widget build(BuildContext context) {
               return MaterialApp(
                 home: Scaffold(
                     appBar: AppBar(
                        title: const Text('Home'),
                    ),// AppBar
                 ), // Scaffold
              ); // MaterialApp
          }
       }
    
    Listagem 4. Código básico para criação de um app com o Widget MaterialApp

    Explicando o código:

    • Linha 1: Importa a biblioteca Material Design
    • Linha 3: Chamada ao método main() o ponto de entrada do app
    • Linha 5: Classe MeuApp
    • LInha 6: Construtor da classe MeuApp
    • Linha 7: @override indica que vamos sobrescrever o método build
    • Linha 8: Método build do Widget
    • Linha 9: Retorna o Widget MaterialApp
    • Linha 10: definindo uma rota home para um Widget Scaffold
    • Linha 11: Widget AppBar para criar a barra do aplicativo
    • Linha 12: Criando um título para a barra do aplicativo com o Widget Text

    Podemos ver o app com o Widget MaterialApp em execução na Figura 1.

    App com StatelessWidget em execução
    Figura 1. App com StatelessWidget em execução

    Exemplo de App com StatefulWidget

    Agora um exemplo de app utilzando MaterialApp e StatefulWidgets que são Widgets que mudam sua visualização de acordo com seu estado. Será um aplicativo bem simples com uma AppBar, um Container, um Center, um Text e um RaisedButton. O Text vai mudar a medida que clicarmos no RaisedButton.

    O código para criar esse app pode ser visto na Listagem 5.

    import 'package:flutter/material.dart';
      
        void main() { 
          runApp(MaterialApp(
            home: MyButton(),
          )); // MaterialApp
        } 
      
        class MyButton extends StatefulWidget {
        @override
        MyButtonState createState() {
          return MyButtonState();
        }
       }
      
       class MyButtonState extends State<MyButton> {
         int counter = 0;
         List<String> strings = ['Flutter','é','legal','e','incrível.'];
         String displayedString = "Olá Mundo!";
      
         void onPressOfButton() {
           setState(() {
             displayedString = strings[counter];
             counter = counter < 4 ? counter + 1 : 0;
           });
         }
    
        @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text(“Exemplo com StatefulWidget”);
              backgroundColor: Colors.green,
            ), // AppBar
            body: Container(
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(displayedString, style: TextStyle(fontSize: 40.0)),
                    Padding(padding: EdgeInsets.all(10.0)),
                    RaisedButton(
                      child: Text(
                        "clique aqui",
                        style: TextStyle(color: Colors.white),
                      ), // Text
                      color: Colors.red,
                      onPressed: onPressOfButton,
                    ), // RaisedButton
                  ], // <Widget>[]
                ), // Column
              ), // Cente
            ), // Container
          );
        }
       }
    
    Listagem 5. Código de um App Flutter com MaterialApp e StatefulWidget

    Explicando o código:

    • Linha 1: Importa a biblioteca flutter/material.dart para aplicar o Material Design ao app
    • Linha 3: Método main() é o ponto de entrada do aplicativo
    • Linha 4: O método runApp chama o MateialApp como o Widget principal
    • Linha 5: definimos a rota home para o Widget MyButton
    • Linha 9: declaração do Widget MyButton que é um StatefulWidget
    • Linha 10 e 11: sobrecarga do método createState
    • Linha 12: O método createState retorna a classe MyButtonState
    • Linha 16: classe MyButtonState que extende a classe State para o objeto MyButton
    • Linha 17: variável counter que irá contar os cliques no botão
    • Linha 18: Declaração de uma lista de strings
    • Linha 19: variável do tipo String displayedString
    • Linha 21: método onPressOfButton que captura o clique do botão
    • Linha 22: setState define o estado do botão
    • Linha 23: ao clique do botão a variável displayedString recebe o elemento da lista strings no índice com valor igual ao da variável counter
    • Linha 24: A variável counter é atualizada de acordo com a avaliação da expressão: counter < 4. Se a expressão for verdadeira o valor da variável counter será incrementado em 1 e se for falsa o valor da variável counter será 0
    • Linhas 28 e 29: sobrecarga do método build que renderiza os Widgets no app.
    • Linha 30: retornamos um Widget Scaffold que é um repositório para outros Widgets
    • Linha 31: Widget AppBar para criar a barra superior do app
    • Linha 32: Propriedade título do AppBar
    • Linha 33: Definida a propriedade backgroundColor ou cor de fundo para verde
    • LInha 35: corpo do Scaffold recebe um Widget Container que terá outros Widgets filhos
    • Linha 36: Widget Center para centralizar conteúdo, filho do Widget Container
    • Linha 37: Widget Column que cria um Layout vertical para alinhar outros Widgets
    • Linha 38: propriedade mainAxisAlignment do Widget Column definindo o alinhamento como central
    • Linha 39: Declaração de children que é uma coleção de Widgets filhos
    • Linha 40: Widget Text que exibe o valor da variável displayedString que muda de acordo com o clique do botão
    • Linha 41: Widget Padding que cria um espaço em branco antes do próximo Widget filho
    • Linha 42: Widget RaisedButton que é um botão que dá uma sensação de volume.
    • Linha 43: Widget Text filho de RaisedButton que é exibido como texto do botão
    • Linha 44: propriedade texto do Widget Text do RaisedButton
    • Linha 45: propriedade estilo do Widget Text do RaisedButton que está definindo a cor do texto como branca
    • Linha 47: propriedade cor do Widget Text do RaisedButton
    • Linha 48: evento onPressed que está levando ao método onPressOfButton quando o botão for clicado
    O método createState() pertence a classe StatefulWidget. As classes que herdarem dela devem sobrescrever esse método para retornar a instância da subclasse recém-criada. Ele basicamente cria o estado mutável para o Widget.

    O método setState() é chamado quando o estado interno do objeto é alterado. Ele define as propriedades no objeto de estado e aciona atualizações na interface. Com isso, quando esse método for executado, o Widget será reconstruído com os valores atualizados.

    Podemos ver o app em execução na Animação 2.

    App criado com Flutter usando StatefulWidget que
responde a mudança de estado
    Animação 1. App criado com Flutter usando StatefulWidget que responde a mudança de estado

    O objetivo desse artigo não é ser uma descrição de todos Widgets do Flutter mas explicar a utilização dos Widgets com alguns exemplos mais básicos. A medida que avançar nos estudos do framework você irá conhecer outros Widgets.

    Confira também