Pular para o conteúdo principal

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

  1. StatelessWidget: Crie um widget MeuTexto que estenda StatelessWidget e receba um texto como parâmetro. O widget deve exibir o texto com estilo personalizado.

  2. StatefulWidget básico: Crie um widget Contador que estenda StatefulWidget. O widget deve ter um contador que começa em 0 e um botão que incrementa o contador quando pressionado.

  3. setState: Modifique o contador do exercício anterior para adicionar um botão de decremento. Use setState para atualizar o estado.

  4. BuildContext: Crie um widget que use BuildContext para 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(),
),
),
));
}