🎨 Crear e aplicar un tema
Un tema define o aspecto xeral da aplicación: as cores, as fontes e os estilos que compartirán os widgets. Así, podemos manter unha aparencia común sen configurar cada botón ou texto por separado.
Para utilizalo, primeiro creamos o tema e despois aplicámolo á aplicación.
🖌️ Crear o tema
En Flutter, creamos os temas con ThemeData. Este exemplo crea un tema a partir dunha cor azul. Colócao despois dos imports, fóra das clases:
final temaCentro = ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue, // Cor de partida para xerar a combinación.
),
);
Neste código:
ThemeDatareúne a configuración visual do tema. Podemos indicar só o que queremos personalizar; o resto conserva os valores predeterminados.colorSchemecontén a combinación de cores da aplicación: fondos, textos, botóns…ColorScheme.fromSeedxera esa combinación a partir da cor indicada enseedColor.
💡 A cor de partida serve para obter varias cores relacionadas. Non significa que todo vaia ser azul.
📲 Aplicar o tema
Dentro do MaterialApp, engade theme: temaCentro:
MaterialApp(
theme: temaCentro, // Aplicamos o tema que creamos.
home: const PantallaCentro(), // Widget coa pantalla inicial da aplicación.
)
PantallaCentro representa o widget que uses como pantalla inicial.
A partir dese momento, os compoñentes Material, como FilledButton ou Card, empregan os estilos do tema automaticamente, salvo que lles indiquemos outros.
💡 Para probar outra combinación, cambia
Colors.blueporColors.green. Non necesitas cambiar a cor de cada widget.
🧪 Exemplo de aplicación do tema
🔗 DartPad:

🖌️ Usar os estilos do tema
Moitos widgets, como Card ou FilledButton, empregan automaticamente o tema da aplicación. Pero tamén podemos consultar as súas cores e estilos para aplicalos a un texto, unha icona ou un fondo.
Para acceder ao tema, escribimos esta liña dentro do método build da pantalla, antes do return:
final tema = Theme.of(context); // Consultamos o tema que recibe esta pantalla.
Theme.of(context) busca o tema que lle corresponde ao widget segundo o lugar que ocupa na aplicación. Gardámolo na variable tema para consultar as súas propiedades facilmente:
| Expresión | Que proporciona? |
|---|---|
tema.colorScheme.primary | Cor principal, útil para destacar elementos. |
tema.colorScheme.surface | Cor de fondo para superficies, como paneis ou tarxetas. |
tema.colorScheme.onSurface | Cor de texto ou iconas pensada para verse sobre surface. |
tema.textTheme.titleLarge | Estilo para un título grande. |
tema.textTheme.bodyMedium | Estilo para o texto habitual. |
🧪 Aplicar os estilos a unha pantalla
Para probalo no programa anterior, substitúe todo o valor de home: Scaffold(...) por home: const PantallaCentro(). Despois engade a seguinte clase fóra de main. Así, a pantalla ten o seu propio build, desde o que pode consultar o tema.
Neste exemplo usamos un estilo de título e a cor principal do tema:
class PantallaCentro extends StatelessWidget {
const PantallaCentro({super.key});
@override
Widget build(BuildContext context) {
final tema = Theme.of(context); // Accedemos ao tema da aplicación.
return Scaffold(
appBar: AppBar(title: const Text('IES San Mamede')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.school,
color: tema.colorScheme.primary, // Cor destacada do tema.
size: 48,
),
const SizedBox(height: 8),
Text(
'2º DAM',
style: tema.textTheme.titleLarge, // Estilo de título do tema.
),
],
),
),
);
}
}
💡 Así, se cambiamos o tema, estes widgets adaptaranse ás súas cores e estilos, sen ter que modificar o código de cada un.

📍 Onde consultamos o tema?
A pantalla debe estar dentro do MaterialApp que define o tema, por exemplo, como o seu home.
Theme.of(context) busca o tema cara arriba na árbore de widgets. Por iso, o context do método que crea o propio MaterialApp non permite acceder ao tema definido dentro del.
Para facelo sinxelo, separamos as responsabilidades: a aplicación configura o tema en MaterialApp e PantallaCentro consúltao no seu build, como no exemplo anterior.
✏️ Crear unha variante con copyWith
O método copyWith permite crear unha copia dun obxecto cambiando só algunhas das súas propiedades. As propiedades que non indiquemos conservan o seu valor orixinal.
Pode empregarse, por exemplo, con ThemeData, TextTheme ou TextStyle.
Neste exemplo partimos dun estilo de texto e creamos outro aumentando o tamaño e poñéndoo en negra:
// Estilo de partida que queremos conservar.
const estiloBase = TextStyle(
fontSize: 16,
color: Colors.blue,
);
// Creamos outro estilo a partir do anterior.
final estiloTitulo = estiloBase.copyWith(
fontSize: 24,
fontWeight: FontWeight.bold,
);
estiloTitulo conserva a cor azul de estiloBase, pero cambia o tamaño e o grosor da fonte. estiloBase non se modifica.
Podemos aplicar o novo estilo a un texto:
Text(
'2º DAM',
style: estiloTitulo, // Aplicamos o estilo que acabamos de crear.
)
Tamén podemos utilizalo para personalizar un tema. No exemplo completo partimos de temaClaroBase e creamos temaClaro modificando só o que nos interesa: os títulos aparecen en negra e os FilledButton teñen máis espazo interior.
Neste exemplo personalizamos só o tema claro. Para conservar os mesmos axustes no escuro, tamén debemos aplicalos ao seu tema.
💡 Un estilo escrito directamente nun widget ten prioridade sobre o estilo herdado do tema. É recomendable reservar estes estilos locais para excepcións. Se queremos modificar todos os botóns do mesmo tipo, debemos facelo no tema, por exemplo mediante
filledButtonTheme.

🌗 Tema claro e escuro
Flutter permite definir un tema claro e outro escuro para que a aplicación poida adaptarse á preferencia do usuario ou do dispositivo.
En MaterialApp utilizamos principalmente estas tres propiedades:
| Propiedade | Para que serve? |
|---|---|
theme | Define o tema claro. |
darkTheme | Define o tema escuro. |
themeMode | Indica que tema debe utilizarse. |
themeMode pode ter tres valores:
ThemeMode.light: utiliza sempre o tema claro.ThemeMode.dark: utiliza sempre o tema escuro.ThemeMode.system: utiliza a configuración do dispositivo.
Por exemplo:
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
),
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark, // Xera cores para o modo escuro.
),
),
themeMode: ThemeMode.system,
home: const PantallaCentro(),
)
brightness: Brightness.dark indica que a combinación de cores debe estar preparada para un fondo escuro.
Neste caso, a aplicación cambia automaticamente entre o tema claro e o escuro segundo a configuración do dispositivo.
📌 Se non definimos
darkTheme, Flutter utilizathemetamén cando se solicita o modo escuro.
Para que ambos os modos funcionen correctamente, evita fixar directamente cores como Colors.black para o texto ou Colors.white para os fondos. É preferible utilizar as cores e os estilos proporcionados polo tema, xa que se adaptarán ao modo claro ou escuro.

🧪 Exemplo completo
Cambia ThemeMode.light por ThemeMode.dark para comparar o título, a tarxeta e o botón. Con ThemeMode.system, o resultado depende da configuración do sistema.
🔗 DartPad:
?. evita chamar a copyWith se o estilo consultado é null, como vimos en Dart. A AppBar pode ter un fondo claro no modo claro: non todos os compoñentes usan primary como fondo.
No Tema 3.3 engadiremos un interruptor que cambia o modo coa aplicación en marcha. Aquí practicamos primeiro a configuración visual.

🔤 Compartir a fonte
Se xa instalaches google_fonts e engadiches o seu import, podes incluír isto dentro de ThemeData:
fontFamily: GoogleFonts.pacifico().fontFamily, // Fonte común deste tema.
Configúraa nos dous temas se queres conservar a mesma fonte ao cambiar de modo. Podes separar as definicións dos temas nun ficheiro como lib/tema.dart e importalo desde main.dart cando o proxecto medre.

📚 Consulta: