Construindo Pontes com o Usuário -
Formulários e Validação
Em quase todos os aplicativos, precisamos coletar informações dos usuários, seja para um
cadastro, uma tela de login, uma pesquisa ou para inserir dados. O Flutter torna a criação de
formulários uma tarefa estruturada e segura, garantindo que os dados inseridos sejam válidos
antes de serem processados.
Os dois widgets centrais para esta tarefa são o Form e o TextFormField.
● Form: Um widget container que agrupa vários campos de formulário. Ele é o maestro
que gerencia o estado geral de todos os campos dentro dele, permitindo validá-los e
salvá-los todos de uma só vez.
● TextFormField: Uma versão mais poderosa do TextField que se integra diretamente
com o Form ancestral. Ele possui funcionalidades cruciais, como a validação de
entrada.
A Chave Mestra: GlobalKey
Para interagir com o Form — para acionar a validação ou salvar seus dados — precisamos de
uma maneira de identificá-lo unicamente na árvore de widgets do Flutter. Para isso, usamos
uma GlobalKey.
Pense na GlobalKey como uma identidade única e permanente para um widget. Mesmo que a
árvore de widgets seja reconstruída, a GlobalKey garante que possamos sempre nos referir
àquele Form específico.
A declaração é feita dentro da classe do seu StatefulWidget:
// 1. Crie uma GlobalKey para o Form.
final _formKey = GlobalKey<FormState>();
E depois, associamos essa chave ao nosso widget Form:
Form(
key: _formKey,
child: Column(
// ... seus campos de formulário aqui ...
),
)
O Guardião do Portão: Validação
A maior vantagem de usar um Form é a validação centralizada. Cada TextFormField pode ter
uma propriedade validator, que é uma função que recebe o valor atual do campo e deve
retornar:
● null, se o valor for válido.
● Uma String com a mensagem de erro, se o valor for inválido.
Vamos ver um exemplo simples para um campo de e-mail e senha:
TextFormField(
decoration: InputDecoration(labelText: 'Email'),
keyboardType: [Link],
validator: (value) {
if (value == null || [Link]) {
return 'Por favor, insira um e-mail.';
}
// Uma verificação simples de e-mail
if () {
return 'Por favor, insira um e-mail válido.';
}
return null; // Válido!
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(labelText: 'Senha'),
obscureText: true, // Esconde o texto da senha
validator: (value) {
if (value == null || [Link] < 6) {
return 'A senha deve ter pelo menos 6 caracteres.';
}
return null; // Válido!
},
),
Acionando a Validação
A validação não acontece magicamente. Precisamos acioná-la, geralmente quando o usuário
tenta submeter o formulário. É aqui que nossa _formKey entra em ação.
Através da chave, podemos acessar o estado atual do formulário (_formKey.currentState) e
chamar o método validate(). Este método executa a função validator de todos os
TextFormField dentro do Form. Se todos retornarem null, validate() retorna true. Se algum
retornar uma mensagem de erro, ele retorna false e exibe as mensagens de erro nos campos
correspondentes.
ElevatedButton(
onPressed: () {
// Valida o formulário.
if (_formKey.currentState!.validate()) {
// Se o formulário for válido, mostramos uma mensagem de sucesso.
[Link](context).showSnackBar(
SnackBar(content: Text('Processando Dados...')),
);
// Aqui você faria o login, salvaria os dados, etc.
}
},
child: Text('Entrar'),
)
Nota: O ! em currentState! é um operador de "null check". Estamos dizendo ao Dart que
temos certeza de que currentState não será nulo neste ponto, pois ele está associado a um
Form que já foi construído.
Exemplo Completo: Uma Tela de Login
Vamos juntar todas as peças em uma tela de login simples e funcional.
login_screen.dart:
import 'package:flutter/[Link]';
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
// A chave global que identifica unicamente o widget Form
// e permite a validação do formulário.
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Tela de Login'),
),
body: Padding(
padding: const [Link](16.0),
// O widget Form atua como um container para os campos.
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: [Link],
children: <Widget>[
// Campo de texto para o e-mail.
TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
keyboardType: [Link],
validator: (value) {
if (value == null || ) {
return 'Por favor, insira um e-mail válido.';
}
return null;
},
),
SizedBox(height: 16.0),
// Campo de texto para a senha.
TextFormField(
decoration: InputDecoration(
labelText: 'Senha',
border: OutlineInputBorder(),
),
obscureText: true,
validator: (value) {
if (value == null || [Link] < 6) {
return 'A senha precisa ter no mínimo 6 caracteres.';
}
return null;
},
),
SizedBox(height: 24.0),
// Botão para submeter o formulário.
ElevatedButton(
onPressed: () {
// Aciona a validação de todos os TextFormField do formulário.
if (_formKey.currentState!.validate()) {
// Se o formulário for válido, prossiga com a lógica.
[Link](context).showSnackBar(
SnackBar(content: Text('Login efetuado com sucesso!')),
);
}
},
child: Text('Entrar'),
style: [Link](
padding: [Link](vertical: 16.0),
),
),
],
),
),
),
);
}
}
Resumo do Capítulo
● Use o widget Form para agrupar e gerenciar campos de entrada.
● Use TextFormField dentro de um Form para obter funcionalidades como validação.
● Uma GlobalKey<FormState> é necessária para interagir com o Form.
● A propriedade validator de um TextFormField define as regras de validação.
● O método _formKey.currentState!.validate() aciona todas as validações e retorna true ou
false.
Com estas ferramentas, você está pronto para construir formulários robustos e amigáveis,
garantindo que os dados que seu aplicativo recebe são exatamente os dados que você
espera.