Widgets Fundamentais
Conceito de Widget
Em Flutter, tudo é um widget. Widgets são componentes de UI que descrevem como a interface deve aparecer. Existem dois tipos principais:
- StatelessWidget: Widgets que não mudam (imutáveis)
- StatefulWidget: Widgets que podem mudar (mutáveis)
Widget tree
Flutter organiza widgets em uma árvore hierárquica:
MaterialApp
└── Scaffold
├── AppBar
└── Column
├── Text
├── Text
└── ElevatedButton
StatelessWidget vs StatefulWidget
StatelessWidget
Widgets que não mantêm estado. Uma vez criados, não mudam:
class MeuTexto extends StatelessWidget {
final String texto;
const MeuTexto({super.key, required this.texto});
Widget build(BuildContext context) {
return Text(texto);
}
}
Quando usar: Quando o widget não precisa mudar após ser criado (textos estáticos, ícones, etc.)
StatefulWidget
Widgets que mantêm estado e podem ser reconstruídos quando o estado muda:
class Contador extends StatefulWidget {
const Contador({super.key});
State<Contador> createState() => _ContadorState();
}
class _ContadorState extends State<Contador> {
int _contador = 0;
void _incrementar() {
setState(() {
_contador++;
});
}
Widget build(BuildContext context) {
return Column(
children: [
Text('Contador: $_contador'),
ElevatedButton(
onPressed: _incrementar,
child: Text('Incrementar'),
),
],
);
}
}
Quando usar: Quando o widget precisa mudar dinamicamente (formulários, listas interativas, animações, etc.)
BuildContext
BuildContext representa a localização de um widget na árvore de widgets. É usado para:
- Acessar temas
- Navegar entre telas
- Mostrar diálogos
- Acessar informações do widget pai
class MeuWidget extends StatelessWidget {
Widget build(BuildContext context) {
// context contém informações sobre este widget na árvore
final tema = Theme.of(context);
return Container(
color: tema.primaryColor,
child: Text('Usando o tema'),
);
}
}
Exercícios
-
StatelessWidget: Crie um widget
MeuTextoque estendaStatelessWidgete receba um texto como parâmetro. O widget deve exibir o texto com estilo personalizado. -
StatefulWidget básico: Crie um widget
Contadorque estendaStatefulWidget. O widget deve ter um contador que começa em 0 e um botão que incrementa o contador quando pressionado. -
setState: Modifique o contador do exercício anterior para adicionar um botão de decremento. Use
setStatepara atualizar o estado. -
BuildContext: Crie um widget que use
BuildContextpara acessar o tema da aplicação e exibir uma cor baseada no tema.
Soluções
Ver solução do exercício 1
import 'package:flutter/material.dart';
class MeuTexto extends StatelessWidget {
final String texto;
const MeuTexto({Key? key, required this.texto}) : super(key: key);
Widget build(BuildContext context) {
return Text(
texto,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
),
);
}
}
void main() {
runApp(MaterialApp(
home: Scaffold(
body: Center(
child: MeuTexto(texto: 'Olá, Flutter!'),
),
),
));
}
Ver solução do exercício 2
import 'package:flutter/material.dart';
class Contador extends StatefulWidget {
State<Contador> createState() => _ContadorState();
}
class _ContadorState extends State<Contador> {
int _contador = 0;
void _incrementar() {
setState(() {
_contador++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Contador')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Contador: $_contador', style: TextStyle(fontSize: 24)),
SizedBox(height: 20),
ElevatedButton(
onPressed: _incrementar,
child: Text('Incrementar'),
),
],
),
),
);
}
}
void main() {
runApp(MaterialApp(home: Contador()));
}
Ver solução do exercício 3
import 'package:flutter/material.dart';
class Contador extends StatefulWidget {
State<Contador> createState() => _ContadorState();
}
class _ContadorState extends State<Contador> {
int _contador = 0;
void _incrementar() {
setState(() {
_contador++;
});
}
void _decrementar() {
setState(() {
_contador--;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Contador')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Contador: $_contador', style: TextStyle(fontSize: 24)),
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _decrementar,
child: Text('-'),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: _incrementar,
child: Text('+'),
),
],
),
],
),
),
);
}
}
void main() {
runApp(MaterialApp(home: Contador()));
}
Ver solução do exercício 4
import 'package:flutter/material.dart';
class WidgetComTema extends StatelessWidget {
Widget build(BuildContext context) {
final tema = Theme.of(context);
return Container(
color: tema.primaryColor,
padding: EdgeInsets.all(20),
child: Text(
'Usando cor do tema',
style: TextStyle(
color: tema.colorScheme.onPrimary,
fontSize: 20,
),
),
);
}
}
void main() {
runApp(MaterialApp(
theme: ThemeData(
primaryColor: Colors.blue,
colorScheme: ColorScheme.light(
primary: Colors.blue,
onPrimary: Colors.white,
),
),
home: Scaffold(
body: Center(
child: WidgetComTema(),
),
),
));
}