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.
-
Row e Column: Crie um layout usando
Rowcom trêsContainercoloridos (vermelho, azul, verde) lado a lado. Depois, crie o mesmo layout usandoColumnpara empilhar os containers verticalmente. -
Expanded e Flexible: Crie um
Rowcom três containers. O primeiro e o terceiro devem ter largura fixa de 50, e o do meio deve usarExpandedpara ocupar o espaço restante. -
Container com decoração: Crie um
Containercom padding, margin, cor de fundo, bordas arredondadas e sombra. UseBoxDecorationpara personalizar a aparência. -
Stack: Crie um
Stackcom um container azul grande e um container vermelho menor sobreposto no centro. Adicione um texto sobre o container vermelho. -
Wrap: Crie um layout usando
Wrapcom múltiplosChipwidgets. 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')),
],
),
),
),
));
}