Pular para o conteúdo principal

Widgets de Layout

Scaffold

Scaffold é o widget básico que implementa a estrutura visual básica de uma página com Material Design:

Scaffold(
appBar: AppBar( // header da página
title: Text('Minha App'),
),
body: Center(
child: Text('Conteúdo'),
),
floatingActionButton: FloatingActionButton( // botão flutuante
onPressed: () {},
child: Icon(Icons.add),
),
drawer: Drawer( // conteúdo que abre estilo "hamburger menu"
child: ListView(
children: [
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
],
),
),
)

Container

Container é um widget versátil que pode conter um único filho e aplicar padding, margin, decoração, etc.:

Container(
width: 200,
height: 100,
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 4,
offset: Offset(0, 2),
),
],
),
child: Text('Conteúdo'),
)

Row, Column, Wrap

Row

Organiza widgets horizontalmente:

Row(
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment configura o alinhamento no eixo principal, em Row é o eixo horizontal
crossAxisAlignment: CrossAxisAlignment.center, // crossAxisAlignment configura o alinhamento no eixo cruzado, em Row é o eixo vertical
children: [
Icon(Icons.star),
SizedBox(width: 8),
Text('Avaliação'),
],
)

Column

Organiza widgets verticalmente:

Column(
mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment configura o alinhamento no eixo principal, em Column é o eixo vertical
crossAxisAlignment: CrossAxisAlignment.start, // crossAxisAlignment configura o alinhamento no eixo cruzado, em Column é o eixo horizontal
children: [
Text('Título'),
SizedBox(height: 8),
Text('Subtítulo'),
],
)

Wrap

Organiza widgets que podem quebrar para a próxima linha:

Wrap(
spacing: 8, // spacing define o espaço horizontal entre widgets na mesma linha
runSpacing: 8, // runSpacing define o espaço vertical entre as linhas quando os widgets quebram
children: [
Chip(label: Text('Tag 1')),
Chip(label: Text('Tag 2')),
Chip(label: Text('Tag 3')),
Chip(label: Text('Tag 4')),
],
)

Expanded e Flexible

Expanded

Ocupa o espaço disponível restante:

Row(
children: [
Container(width: 50, color: Colors.red),
Expanded(
child: Container(color: Colors.blue),
),
Container(width: 50, color: Colors.green),
],
)

Flexible

Similar ao Expanded, mas com mais controle sobre como o espaço é usado:

Row(
children: [
Flexible(
flex: 2, // a soma dos flex é 3, então esse widget vai ocupar 2 terços da largura disponível
child: Container(color: Colors.red),
),
Flexible(
flex: 1, // a soma dos flex é 3, então esse widget vai ocupar 1 terço da largura disponível
child: Container(color: Colors.blue),
),
],
)

Stack

Sobrepoem widgets uns sobre os outros:

Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
color: Colors.blue,
),
Container(
width: 100,
height: 100,
color: Colors.red,
),
Text('Sobreposto'),
],
)

Padding e Margin

Padding

Adiciona espaço interno ao widget:

Padding(
padding: EdgeInsets.all(16),
child: Text('Texto com padding'),
)

// Ou usando EdgeInsets específico
Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Text('Texto'),
)

Padding(
padding: EdgeInsets.only(left: 16, top: 8),
child: Text('Texto'),
)

Margin

Adiciona espaço externo (usando Container):

Container(
margin: EdgeInsets.all(16),
child: Text('Texto com margin'),
)

SizedBox

Cria um espaço fixo ou um widget com tamanho específico:

// Espaçamento
Column(
children: [
Text('Primeiro'),
SizedBox(height: 20),
Text('Segundo'),
],
)

// Widget com tamanho fixo
SizedBox(
width: 100,
height: 100,
child: Container(color: Colors.blue),
)

Exercícios

* Sempre use Scaffold para criar a estrutura da página.

  1. Row e Column: Crie um layout usando Row com três Container coloridos (vermelho, azul, verde) lado a lado. Depois, crie o mesmo layout usando Column para empilhar os containers verticalmente.

  2. Expanded e Flexible: Crie um Row com três containers. O primeiro e o terceiro devem ter largura fixa de 50, e o do meio deve usar Expanded para ocupar o espaço restante.

  3. Container com decoração: Crie um Container com padding, margin, cor de fundo, bordas arredondadas e sombra. Use BoxDecoration para personalizar a aparência.

  4. Stack: Crie um Stack com um container azul grande e um container vermelho menor sobreposto no centro. Adicione um texto sobre o container vermelho.

  5. Wrap: Crie um layout usando Wrap com múltiplos Chip widgets. Demonstre como os chips quebram para a próxima linha quando não há espaço suficiente.

Soluções

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

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Layout')),
body: Column(
children: [
Text('Row:', style: TextStyle(fontSize: 20)),
Row(
children: [
Container(width: 100, height: 100, color: Colors.red),
Container(width: 100, height: 100, color: Colors.blue),
Container(width: 100, height: 100, color: Colors.green),
],
),
SizedBox(height: 20),
Text('Column:', style: TextStyle(fontSize: 20)),
Column(
children: [
Container(width: 100, height: 100, color: Colors.red),
Container(width: 100, height: 100, color: Colors.blue),
Container(width: 100, height: 100, color: Colors.green),
],
),
],
),
),
));
}
Ver solução do exercício 2
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Expanded')),
body: Row(
children: [
Container(width: 50, height: 100, color: Colors.red),
Expanded(
child: Container(height: 100, color: Colors.blue),
),
Container(width: 50, height: 100, color: Colors.green),
],
),
),
));
}
Ver solução do exercício 3
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
body: Center(
child: Container(
padding: EdgeInsets.all(20),
margin: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(15),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(0, 5),
),
],
),
child: Text(
'Container decorado',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
),
));
}
Ver solução do exercício 4
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
body: Center(
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
color: Colors.blue,
),
Container(
width: 100,
height: 100,
color: Colors.red,
),
Text(
'Sobreposto',
style: TextStyle(color: Colors.white, fontSize: 16),
),
],
),
),
),
));
}
Ver solução do exercício 5
import 'package:flutter/material.dart';

void main() {
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Wrap')),
body: Padding(
padding: EdgeInsets.all(16),
child: Wrap(
spacing: 8,
runSpacing: 8,
children: [
Chip(label: Text('Tag 1')),
Chip(label: Text('Tag 2')),
Chip(label: Text('Tag 3')),
Chip(label: Text('Tag 4')),
Chip(label: Text('Tag 5')),
Chip(label: Text('Tag 6')),
Chip(label: Text('Tag 7')),
Chip(label: Text('Tag 8')),
],
),
),
),
));
}