Pular para o conteúdo principal

Input e Formulários

TextField

Campo de texto para entrada do usuário:

TextField(
decoration: InputDecoration(
labelText: 'Nome',
hintText: 'Digite seu nome',
border: OutlineInputBorder(),
),
onChanged: (value) {
print('Valor digitado: $value');
},
)

Com controller:

class MeuFormulario extends StatefulWidget {

State<MeuFormulario> createState() => _MeuFormularioState();
}

class _MeuFormularioState extends State<MeuFormulario> {
final _controller = TextEditingController();


void dispose() {
_controller.dispose();
super.dispose();
}


Widget build(BuildContext context) {
return TextField(
controller: _controller,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
);
}
}

Form

Form agrupa e valida múltiplos campos:

class FormularioCompleto extends StatefulWidget {

State<FormularioCompleto> createState() => _FormularioCompletoState();
}

class _FormularioCompletoState extends State<FormularioCompleto> {
final _formKey = GlobalKey<FormState>();
final _nomeController = TextEditingController();
final _emailController = TextEditingController();


void dispose() {
_nomeController.dispose();
_emailController.dispose();
super.dispose();
}

void _enviar() {
if (_formKey.currentState!.validate()) {
print('Nome: ${_nomeController.text}');
print('Email: ${_emailController.text}');
}
}


Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _nomeController,
decoration: InputDecoration(labelText: 'Nome'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Por favor, digite seu nome';
}
return null;
},
),
TextFormField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Por favor, digite seu email';
}
if (!value.contains('@')) {
return 'Email inválido';
}
return null;
},
),
ElevatedButton(
onPressed: _enviar,
child: Text('Enviar'),
),
],
),
);
}
}

Validação

Validação pode ser feita de várias formas:

TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Campo obrigatório';
}
if (value.length < 3) {
return 'Mínimo de 3 caracteres';
}
return null; // null significa que a validação passou
},
)

Exercícios

  1. TextField básico: Crie um TextField simples com um label e um hint. Exiba o valor digitado em um Text abaixo do campo.

  2. TextEditingController: Crie um formulário com dois campos (nome e email) usando TextEditingController. Adicione um botão que limpe ambos os campos quando pressionado.

  3. Form com validação: Crie um Form com dois campos: nome (obrigatório, mínimo 3 caracteres) e email (obrigatório, deve conter @). Exiba mensagens de erro quando a validação falhar.

  4. Validação customizada: Crie um campo de senha com validação que verifique se a senha tem pelo menos 8 caracteres e contém pelo menos um número.

  5. Formulário completo: Crie um formulário completo com nome, email, telefone e mensagem. Todos os campos devem ser validados e o formulário só deve ser submetido se todos estiverem válidos.

Soluções

Ver solução do exercício 1
import 'package:flutter/material.dart';

class CampoTexto extends StatefulWidget {

State<CampoTexto> createState() => _CampoTextoState();
}

class _CampoTextoState extends State<CampoTexto> {
String _texto = '';


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('TextField')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
decoration: InputDecoration(
labelText: 'Digite algo',
hintText: 'Ex: Olá, Flutter!',
border: OutlineInputBorder(),
),
onChanged: (value) {
setState(() {
_texto = value;
});
},
),
SizedBox(height: 20),
Text('Valor: $_texto'),
],
),
),
);
}
}

void main() {
runApp(MaterialApp(home: CampoTexto()));
}
Ver solução do exercício 2
import 'package:flutter/material.dart';

class FormularioController extends StatefulWidget {

State<FormularioController> createState() => _FormularioControllerState();
}

class _FormularioControllerState extends State<FormularioController> {
final _nomeController = TextEditingController();
final _emailController = TextEditingController();


void dispose() {
_nomeController.dispose();
_emailController.dispose();
super.dispose();
}

void _limpar() {
_nomeController.clear();
_emailController.clear();
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Formulário')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: _nomeController,
decoration: InputDecoration(
labelText: 'Nome',
border: OutlineInputBorder(),
),
),
SizedBox(height: 16),
TextField(
controller: _emailController,
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _limpar,
child: Text('Limpar'),
),
],
),
),
);
}
}

void main() {
runApp(MaterialApp(home: FormularioController()));
}
Ver solução do exercício 3
import 'package:flutter/material.dart';

class FormValidacao extends StatefulWidget {

State<FormValidacao> createState() => _FormValidacaoState();
}

class _FormValidacaoState extends State<FormValidacao> {
final _formKey = GlobalKey<FormState>();

void _enviar() {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Formulário válido!')),
);
}
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Validação')),
body: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'Nome',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nome é obrigatório';
}
if (value.length < 3) {
return 'Nome deve ter pelo menos 3 caracteres';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email é obrigatório';
}
if (!value.contains('@')) {
return 'Email inválido';
}
return null;
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _enviar,
child: Text('Enviar'),
),
],
),
),
),
);
}
}

void main() {
runApp(MaterialApp(home: FormValidacao()));
}
Ver solução do exercício 4
import 'package:flutter/material.dart';

class SenhaValidacao extends StatefulWidget {

State<SenhaValidacao> createState() => _SenhaValidacaoState();
}

class _SenhaValidacaoState extends State<SenhaValidacao> {
final _formKey = GlobalKey<FormState>();

bool _validarSenha(String? senha) {
if (senha == null || senha.isEmpty) {
return false;
}
if (senha.length < 8) {
return false;
}
if (!senha.contains(RegExp(r'[0-9]'))) {
return false;
}
return true;
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Validação de Senha')),
body: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
obscureText: true,
decoration: InputDecoration(
labelText: 'Senha',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Senha é obrigatória';
}
if (value.length < 8) {
return 'Senha deve ter pelo menos 8 caracteres';
}
if (!value.contains(RegExp(r'[0-9]'))) {
return 'Senha deve conter pelo menos um número';
}
return null;
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Senha válida!')),
);
}
},
child: Text('Validar'),
),
],
),
),
),
);
}
}

void main() {
runApp(MaterialApp(home: SenhaValidacao()));
}
Ver solução do exercício 5
import 'package:flutter/material.dart';

class FormularioCompleto extends StatefulWidget {

State<FormularioCompleto> createState() => _FormularioCompletoState();
}

class _FormularioCompletoState extends State<FormularioCompleto> {
final _formKey = GlobalKey<FormState>();

void _enviar() {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Formulário enviado com sucesso!')),
);
}
}


Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Formulário Completo')),
body: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'Nome',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nome é obrigatório';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
labelText: 'Email',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Email é obrigatório';
}
if (!value.contains('@')) {
return 'Email inválido';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
decoration: InputDecoration(
labelText: 'Telefone',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Telefone é obrigatório';
}
return null;
},
),
SizedBox(height: 16),
TextFormField(
maxLines: 4,
decoration: InputDecoration(
labelText: 'Mensagem',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Mensagem é obrigatória';
}
return null;
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _enviar,
child: Text('Enviar'),
),
],
),
),
),
);
}
}

void main() {
runApp(MaterialApp(home: FormularioCompleto()));
}