Theme e ThemeData — os mecanismos centrais de tematização no Flutter, que permitem definir cores, fontes, margens e estilos de componentes globalmente para toda a aplicação. ThemeData é um objeto de configuração passado ao MaterialApp através do parâmetro theme. De acordo com a documentação oficial do Flutter (2026), a configuração correta do ThemeData reduz o código de estilização duplicado em 70–80% e garante uma aparência visual uniforme em todas as telas. O sistema de herança embutido permite sobrescrever o tema ao nível de widgets individuais através de Theme.of(context).
Pontos principais
ThemeData é uma classe que contém a descrição completa do estilo visual de uma aplicação Material. É passada ao MaterialApp através do parâmetro theme ou darkTheme e é herdada por todos os widgets filhos. Cada widget do Material Design usa ThemeData para obter seus estilos: cores dos botões, tamanhos da AppBar, estilos de texto, margens dos cartões e ícones.
No centro do ThemeData está o ColorScheme, que define as cores primary, secondary, surface, error e outras. A partir dessas cores, os estados (hover, focus, pressed) são automaticamente calculados para todos os componentes Material. Por exemplo, ElevatedButton usa a cor primary para o fundo e onPrimary para o texto — sem configuração adicional.
O widget Theme é um InheritedWidget que propaga o tema para baixo na árvore de widgets. Qualquer widget pode aceder ao tema atual através de Theme.of(context) e também pode criar um novo tema baseado no existente com valores sobrescritos através de Theme.copyWith ou ThemeData.copyWith.
Em resumo: ThemeData é a fonte única de estilos da aplicação. Comece o desenvolvimento definindo ThemeData — isto define a linguagem visual de todo o projeto e evita estilos dispersos em diferentes ecrãs.
ColorScheme é o elemento central da tematização no Material 3. Substitui os obsoletos primarySwatch e primaryColor, fornecendo um conjunto completo de cores para todos os estados e componentes.
ColorScheme contém 12 cores principais: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline e shadow. Para cada cor, as variantes clara e escura são automaticamente calculadas, bem como as cores para os estados hover, focus, pressed e dragged. Quando apenas primary é especificado, o framework gera automaticamente as cores restantes através de ColorScheme.fromSeed.
O método ColorScheme.fromSeed (Material 3) aceita uma cor base seedColor e gera uma paleta harmoniosa completa baseada no algoritmo Material Design 3. Isto elimina a necessidade de seleção manual de cores complementares e análogas. Basta passar uma cor primária da marca, e ColorScheme.fromSeed cria uma paleta coesa para todo o sistema Material.
Em resumo: em projetos novos, use ColorScheme.fromSeed para gerar a paleta. Para compatibilidade com Material 2 — use primarySwatch. ColorScheme é o mínimo exigido para Material 3.
TextTheme é uma parte do ThemeData que define os estilos de texto para todos os níveis de cabeçalhos, subcabeçalhos, corpo e etiquetas. Material Design define 15 estilos de texto: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium e outros.
A tipografia é definida ou através de GoogleFonts para carregamento automático de fontes, ou através do embutido Theme.of(context).textTheme com objetos TextStyle personalizados. GoogleFonts fornece centenas de fontes através do pacote google_fonts, que as armazena em cache localmente após o primeiro carregamento. A alternativa é incorporar fontes nos assets do projeto através de pubspec.yaml.
Para tipografia adaptativa, TextTheme suporta MediaQuery.textScaleFactor — quando o tamanho da fonte do sistema aumenta, todos os estilos de texto escalam proporcionalmente. Além disso, podem ser definidos diferentes tamanhos de fonte para diferentes fatores de forma usando isTest dependendo de MediaQuery.size.width.
Em resumo: defina TextTheme no ThemeData e use Theme.of(context).textTheme para todos os elementos de texto. Isto garante consistência de fontes e simplifica alterações globais de tipografia.
Theme é um InheritedWidget que propaga o tema de pais para filhos. Qualquer widget filho pode tanto ler o tema atual através de Theme.of(context) como criar a sua própria cópia com alterações através de ThemeData.copyWith.
Mecanismo de herança: se um widget está envolvido num Theme com novos dados, todos os seus descendentes veem o tema sobrescrito, enquanto os widgets fora deste invólucro veem o original. Isto permite, por exemplo, isolar estilos para um ecrã específico: um cabeçalho usa um tema personalizado com um AppBarTheme modificado, enquanto o resto da aplicação usa o padrão.
O aninhamento de Theme pode ser ilimitado. Flutter usa uma pesquisa hierárquica: ao chamar Theme.of(context), o framework sobe na árvore até ao primeiro Theme e devolve o seu tema. Se nenhum Theme for encontrado — é lançada uma exceção. Portanto, MaterialApp envolve sempre a aplicação num Theme.
Em resumo: a herança de Theme é um mecanismo flexível para isolar estilos. Use a sobrescrita do tema para ecrãs individuais sem duplicar a configuração global.
Tema escuro é a capacidade embutida do Flutter de alternar entre temas claro e escuro. ThemeData é armazenado nos parâmetros theme (claro) e darkTheme (escuro) do MaterialApp. O parâmetro themeMode controla o modo: ThemeMode.light (sempre claro), ThemeMode.dark (sempre escuro) ou ThemeMode.system (segue as definições do sistema).
Ao implementar um tema escuro, não é necessário recriar todos os estilos do zero. Basta passar ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) para darkTheme. O framework ajustará automaticamente as cores para um fundo escuro: surface torna-se cinzento escuro, o texto torna-se claro. Outros subtemas (AppBarTheme, CardTheme, BottomNavigationBarTheme) são herdados da versão clara a menos que explicitamente sobrescritos.
Para transições suaves entre temas, o Flutter fornece animação através de AnimatedTheme. Ao alterar themeMode, as cores e estilos animam-se, criando uma transição visualmente agradável. AnimatedTheme usa Duration e Curve para configurar a velocidade da animação.
Em resumo: o tema escuro é implementado através de darkTheme e ColorScheme.fromSeed com brightness: Brightness.dark. Use ThemeMode.system para seguir as definições de sistema do utilizador.
Exemplo 1 — configuração global do tema através de MaterialApp usando ColorScheme.fromSeed.
final ThemeData appTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.indigo,
brightness: Brightness.light,
),
appBarTheme: const AppBarTheme(
centerTitle: true,
elevation: 0,
),
cardTheme: const CardTheme(
elevation: 2,
margin: EdgeInsets.all(8),
),
);
return MaterialApp(
theme: appTheme,
themeMode: ThemeMode.system,
home: const MyHomePage(),
);
Este exemplo cria um ThemeData com Material 3, um esquema de cores baseado em índigo e estilos personalizados de AppBar e Card. useMaterial3 ativa o novo sistema de temas Material 3, e ColorScheme.fromSeed gera a paleta completa.
Exemplo 2 — acesso ao tema e sobrescrita para uma parte da aplicação.
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Column(
children: [
Text(
'Standard headline',
style: theme.textTheme.headlineMedium,
),
Theme(
data: theme.copyWith(
colorScheme: theme.colorScheme.copyWith(
primary: Colors.orange,
),
),
child: const SpecialSection(),
),
],
);
}
O segundo exemplo demonstra o uso de Theme.of(context) para ler estilos e Theme() com copyWith para sobrescrever o tema numa parte da árvore sem alterar a configuração global. SpecialSection dentro de Theme receberá a cor primary laranja, enquanto o resto da aplicação mantém o índigo original.
Em resumo: o tema global é definido no MaterialApp, acedido através de Theme.of(context) e sobrescrito através de Theme com copyWith. Para Material 3, use ColorScheme.fromSeed.
Erro 1: usar primarySwatch em vez de ColorScheme no Material 3. primarySwatch está obsoleto e não é suportado no Material 3. Ao usar useMaterial3: true com primarySwatch, o Flutter emite um aviso. Solução: migrar para ColorScheme.fromSeed para geração da paleta.
Erro 2: codificar cores diretamente nos widgets em vez de usar Theme.of(context). Os programadores escrevem Colors.blue diretamente num Container em vez da cor primary ou secondary do tema. Ao mudar o tema, estas cores permanecem inalteradas, quebrando a consistência do estilo. Solução: use sempre Theme.of(context).colorScheme.primary ou outras cores do tema.
Erro 3: falta de darkTheme. Se a aplicação não definir darkTheme, quando o tema escuro é ativado no dispositivo, o Flutter tenta adaptar o tema claro automaticamente, o que frequentemente dá um resultado de baixa qualidade. Solução: passe sempre darkTheme ao MaterialApp, mesmo que o tema escuro não seja uma prioridade — isto é importante para a experiência do utilizador.
Erro 4: criar um novo tema em cada build. Se ThemeData for criado dentro do método build, cada reconstrução do widget cria um novo objeto de tema, quebrando a otimização do InheritedWidget. Solução: mover ThemeData para um campo static ou construtor const fora do build.
Em resumo: a tematização correta requer uma abordagem centralizada. Mova ThemeData para constantes, use esquemas de cores do tema e defina sempre ambos os temas — claro e escuro.
Perguntas frequentes
ThemeData são os dados de configuração (cores, fontes, estilos). Theme é um InheritedWidget que transmite ThemeData para baixo na árvore de widgets. Theme.of(context) devolve o ThemeData que o Theme mais próximo propaga no contexto atual.
Controle themeMode no MaterialApp através do estado da aplicação. Altere o estado de ThemeMode.light para ThemeMode.dark, e o Flutter reconstruirá toda a árvore com o novo tema. Para animação suave, use AnimatedTheme.
ColorScheme.fromSeed é um método do Material 3 que aceita uma cor base (seedColor) e gera uma paleta harmoniosa completa: primary, secondary, tertiary, surface, error e suas variantes on. Permite obter um esquema de cores coerente a partir de uma única cor de marca.
Através de TextTheme dentro de ThemeData: especifique TextStyle com fontFamily para cada nível. Para Google Fonts, use o pacote google_fonts, passando fontFamily diretamente para TextTheme. Para fontes locais — inclua-as através de pubspec.yaml na secção fonts.
Sim. Envolva o ecrã num Theme com dados sobrescritos através de copyWith. Todos os widgets filhos dentro deste Theme receberão os estilos modificados, enquanto o resto da aplicação mantém o tema original. Isto não cria sobrecarga adicional.
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