Flutter Widgets — o que é, árvore de widgets e build

Autor: IT Sectr Publicado: 2026-02-21 Tempo de leitura: 8 min

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 Flutter: de telas e botões a preenchimento e alinhamento; o framework não usa componentes nativos da plataforma.
  • StatelessWidget — um widget sem estado mutável; exibe dados passados através do construtor e não muda após o build.
  • StatefulWidget — um widget com estado mutável armazenado em um objeto State separado que sobrevive a rebuilds.
  • Árvore de widgets (widget tree) — uma hierarquia de widgets que descreve a UI; o Flutter a transforma em Element Tree e Render Tree para renderização.
  • BuildContext — o contexto de construção que fornece acesso à posição do widget na árvore, tema, MediaQuery e InheritedWidget.

O que são Flutter Widgets?

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.

As três árvores do Flutter

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: widgets imutáveis

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.

dart
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: widgets com estado

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.

dart
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.

Árvore de widgets: de Widget a RenderObject

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).

dart
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: contexto de construção e acesso à árvore

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: identificação do widget na árvore

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).

Catálogo de widgets Flutter: Material, Cupertino, Layout

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.

CategoriaWidgets chavePropósito
LayoutRow, Column, Stack, Container, Expanded, FlexiblePosicionamento e dimensionamento de filhos
MaterialScaffold, AppBar, Card, Drawer, FAB, TabBarComponentes UI do Material Design 3
CupertinoCupertinoPageScaffold, CupertinoNavigationBar, CupertinoButtonComponentes com estilo iOS
PaintingOpacity, ClipRect, Transform, DecoratedBox, BackdropFilterEfeitos visuais e recorte
AsyncFutureBuilder, StreamBuilderCarregamento de dados assíncrono com estados de UI
AccessibilitySemantics, MergeSemanticsMarcação semântica para leitores de tela

Perguntas Frequentes

Como StatelessWidget difere de StatefulWidget?

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.

O que é BuildContext no Flutter?

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.

Preciso saber Dart para trabalhar com Flutter?

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.

Flutter é apenas para plataformas móveis?

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.

Como o Flutter alcança desempenho de 60 FPS?

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

  • Flutter Widgets — todos os elementos de UI: de Scaffold a SizedBox; o Flutter os renderiza por conta própria no Skia/Impeller, sem usar componentes nativos.
  • StatelessWidget — um widget sem estado; build() retorna UI baseada em parâmetros imutáveis do construtor.
  • StatefulWidget — um widget com estado mutável em State; setState() desencadeia o rebuild da UI.
  • Três árvores do Flutter: Widget (configuração) → Element (posição) → Render (layout + paint); Element é reutilizado por desempenho.
  • BuildContext — a posição do widget na árvore; acesso a MediaQuery, Theme, Navigator, InheritedWidget.
  • Material e Cupertino — dois conjuntos de widgets para Google Material Design 3 e Apple HIG respectivamente.
  • Key (ValueKey, ObjectKey, UniqueKey) — identificação do widget ao mudar ordem ou quantidade em uma lista.

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.

Discutir o projeto

Leia também