Flutter Widgets — os blocos de construção básicos da interface do usuário no framework Google Flutter, lançado na versão estável 1.0 em dezembro de 2018. No Flutter, tudo é um widget: de telas e botões a preenchimento e alinhamento. Os widgets formam uma árvore (widget tree) que o Flutter renderiza em seu próprio motor Skia/Impeller, ignorando os componentes nativos da plataforma. De acordo com o Google I/O (2025), o Flutter é usado em mais de 500.000 aplicativos no Google Play e na App Store. A arquitetura do Flutter divide os widgets em StatelessWidget (imutáveis) e StatefulWidget (com estado mutável através de um objeto State).
Pontos Principais
Flutter Widgets — todos os elementos de UI no framework Flutter, implementados como classes Dart imutáveis. Um widget é a configuração de um elemento de UI: seu tamanho, cor, posição e manipuladores de eventos. Ao contrário do Android (XML + View) ou iOS (Storyboard + UIView), o Flutter não usa componentes nativos — tudo é desenhado pelo motor Skia (Android/iOS/Linux) ou Impeller (iOS/macOS) em um Canvas. Isso garante uma aparência consistente em todas as plataformas sem discrepâncias de plataforma. O Flutter vem com dois conjuntos de widgets: Material Widgets (Google Material Design 3 para Android/web) e Cupertino Widgets (Apple HIG para iOS/macOS). O desenvolvedor pode combinar ambos os conjuntos em um único aplicativo. Cada widget tem um método build() que retorna um widget filho ou uma composição deles — é assim que a árvore de widgets é construída.
O Flutter opera com três árvores: Widget Tree (configuração, criada pelo desenvolvedor), Element Tree (mapeamento do widget à sua posição na árvore, gerenciado pelo framework) e Render Tree (objetos que calculam o layout e realizam a pintura). Um Widget cria um Element, que cria um RenderObject. O Element é reutilizado quando a configuração muda (rebuild) — este é o mecanismo de otimização do Flutter: se o tipo do widget e a key coincidem, o Element não é recriado, mas atualizado com a nova configuração. Entender as três árvores é a chave para otimizar o desempenho de aplicativos Flutter.
StatelessWidget — um widget que não armazena estado interno. Ele recebe parâmetros através do construtor e os exibe sem possibilidade de alteração após o build. StatelessWidget é ideal para elementos estáticos: cabeçalhos, ícones, avatares, listas com dados fixos. O método build() é chamado uma vez na criação e quando o widget pai muda. Como StatelessWidget não tem estado, não requer um objeto State separado — build() é definido diretamente na classe do widget.
import 'package:flutter/material.dart';
class ProfileHeader extends StatelessWidget {
final String name;
final String avatarUrl;
const ProfileHeader({super.key, required this.name, required this.avatarUrl});
@override
Widget build(BuildContext context) {
return Row(
children: [
CircleAvatar(
radius: 24,
backgroundImage: NetworkImage(avatarUrl),
),
const SizedBox(width: 12),
Text(
name,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
);
}
}ProfileHeader — um StatelessWidget que recebe name e avatarUrl através do construtor. CircleAvatar exibe o avatar, Text exibe o nome. O widget não pode alterar esses valores após a criação. Usar um construtor const (const ProfileHeader) permite que o Flutter reutilize a instância do widget durante o rebuild do pai — uma micro-otimização recomendada para todos os StatelessWidget.
StatefulWidget — um widget com estado mutável armazenado em um objeto State separado. O StatefulWidget em si é imutável, como StatelessWidget. A parte mutável é delegada ao State: State é um objeto criado uma vez que sobrevive a múltiplos rebuilds do widget. Quando o estado muda (setState()), o Flutter chama build() no State, atualizando a UI. StatefulWidget é usado para elementos interativos: contadores, campos de texto, caixas de seleção, animações, temporizadores.
import 'package:flutter/material.dart';
class LikeButton extends StatefulWidget {
const LikeButton({super.key});
@override
State<LikeButton> createState() => _LikeButtonState();
}
class _LikeButtonState extends State<LikeButton> {
bool liked = false;
int count = 42;
void _toggleLike() {
setState(() {
liked = !liked;
count += liked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _toggleLike,
child: Text(liked ? '♥ $count' : '♡ $count'),
);
}
}LikeButton — um StatefulWidget com a classe State _LikeButtonState. Os campos liked e count são estado armazenado em State e não são redefinidos no rebuild. setState() notifica o Flutter de que a UI precisa ser reconstruída. O Flutter não recria State a cada rebuild do pai — apenas quando a configuração muda (key ou tipo do widget). Na IT Sectr, usamos StatelessWidget para exibição e StatefulWidget para componentes interativos, seguindo o princípio de minimizar StatefulWidget até os limites da mutação.
Widget Tree — uma estrutura hierárquica de widgets que descreve a UI do aplicativo. O Flutter converte a Widget Tree em Element Tree: cada Widget cria um Element, que rastreia sua posição na árvore e sua conexão com um RenderObject. A Render Tree realiza o layout (determinação de tamanhos e posições) e o paint (renderização). O Element é uma camada de otimização chave: se o tipo do widget e a key não mudaram durante um rebuild, o Element é reutilizado, atualizando a configuração sem recriar o RenderObject. Isso garante o desempenho do Flutter em altas taxas de quadros (60/120 FPS).
import 'package:flutter/material.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Widgets do Flutter')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.flutter_dash, size: 80),
const SizedBox(height: 16),
const Text(
'Olá, Flutter!',
style: TextStyle(fontSize: 24),
),
],
),
),
);
}
}Árvore de widgets HomeScreen: Scaffold → AppBar + Center → Column → [Icon, SizedBox, Text]. Scaffold é o widget raiz de layout do Material Design. Center centraliza sua Column filha. Column organiza os filhos verticalmente com alinhamento central (mainAxisAlignment.center). O Flutter calcula o layout de cima para baixo (as constraints são passadas do pai) e os tamanhos de baixo para cima (sizedByParent ou sizing from children).
BuildContext — um descritor da posição do widget na Element Tree. Cada método build() recebe um BuildContext, através do qual o widget pode acessar: MediaQuery (tamanho da tela, orientação, densidade de pixels, safe area), Theme (MaterialThemeData ou CupertinoThemeData), Navigator (pilha de navegação), ScaffoldMessenger (SnackBar), InheritedWidget (passagem de dados para baixo na árvore). BuildContext não deve ser salvo após o build() terminar ou usado fora de um contexto síncrono — isso causa erros como “Scaffold.of() called with a context that does not contain a Scaffold”. Em vez de salvar context, use o widget Builder ou o padrão InheritedWidget para acessar dados.
Key — um parâmetro opcional do construtor de cada widget (super.key). Key ajuda o Flutter a identificar um widget quando a ordem ou quantidade de itens em uma lista muda. Sem key, o Flutter compara widgets por tipo e posição; ao adicionar um item no meio de uma lista sem key, o Flutter reutiliza o Element para o widget errado, causando bugs de estado (StatefulWidget) e problemas de animação. Use ValueKey (identificador único) para listas, ObjectKey (baseado no objeto de dados), UniqueKey (garantido único em cada rebuild — para recriação forçada).
Flutter SDK (versão estável 3.3+, Dart 3+) inclui mais de 200 widgets integrados divididos em categorias: Layout (Row, Column, Stack, Container, Expanded, Flexible, Wrap, GridView, ListView, CustomScrollView), Material Design (Scaffold, AppBar, Card, Drawer, BottomNavigationBar, FloatingActionButton, TabBar, Chip, DataTable), Cupertino (CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton, CupertinoTabBar), Painting & Effects (Opacity, DecoratedBox, ClipRect, Transform, BackdropFilter, ShaderMask), Async (FutureBuilder, StreamBuilder) e Accessibility (Semantics, MergeSemantics, ExcludeSemantics). Os widgets de layout são a base de qualquer UI Flutter: Row para sequências horizontais, Column para verticais, Stack para elementos sobrepostos, Container com BoxDecoration para decoração.
| Categoria | Widgets chave | Propósito |
|---|---|---|
| Layout | Row, Column, Stack, Container, Expanded, Flexible | Posicionamento e dimensionamento de filhos |
| Material | Scaffold, AppBar, Card, Drawer, FAB, TabBar | Componentes UI do Material Design 3 |
| Cupertino | CupertinoPageScaffold, CupertinoNavigationBar, CupertinoButton | Componentes com estilo iOS |
| Painting | Opacity, ClipRect, Transform, DecoratedBox, BackdropFilter | Efeitos visuais e recorte |
| Async | FutureBuilder, StreamBuilder | Carregamento de dados assíncrono com estados de UI |
| Accessibility | Semantics, MergeSemantics | Marcação semântica para leitores de tela |
Perguntas Frequentes
StatelessWidget não tem estado interno — todos os dados são passados através do construtor e não mudam. StatefulWidget armazena estado mutável em um objeto State separado que sobrevive a rebuilds. A mudança de estado chama setState(), e o Flutter reconstrói a UI. Use StatelessWidget para elementos imutáveis; use StatefulWidget para elementos interativos.
BuildContext é um descritor da posição do widget na Element Tree, passado ao método build(). Através do context, um widget acessa MediaQuery, Theme, Navigator, ScaffoldMessenger e InheritedWidget. BuildContext não deve ser salvo após o build() terminar. Para acessar dados, use o widget Builder ou InheritedWidget.
Sim, o Flutter usa Dart como sua única linguagem de programação. Dart é uma linguagem estaticamente tipada com null safety, sound null safety, extension methods e pattern matching. Para começar, conhecimento básico de Dart é suficiente: classes, funções, async/await, coleções. Dart compila para código nativo (AOT) via Dart Native e para JavaScript (para web) via Dart2JS.
Não, o Flutter suporta seis plataformas: iOS, Android, Web, macOS, Windows, Linux. Mais de 90% do código é compartilhado entre todas as plataformas. As adaptações de plataforma (câmera, sistema de arquivos) são implementadas através de plugins ou platform channels. Para desktop, o Flutter usa o shell de janelas Flutter Desktop; para web, usa o motor CanvasKit (WebGL) ou renderizador HTML.
O Flutter alcança 60/120 FPS através de: seu próprio motor 2D (Skia/Impeller), ausência de bridge nativa (ao contrário do React Native), três árvores (Widget → Element → Render) com reutilização de Element quando tipo/key permanecem inalterados, um algoritmo de layout com passagem unidirecional (constraints para baixo, sizes para cima) e RepaintBoundary para isolar o repintado de áreas individuais da tela.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também