Theme y ThemeData — qué son, principios y configuración de estilos

Autor: IT Sectr Publicado: 2026-07-03 Tiempo de lectura: 8 min

Theme y ThemeData — los mecanismos centrales de tematización en Flutter que permiten definir colores, fuentes, rellenos y estilos de componentes de forma global para toda la aplicación. ThemeData es un objeto de configuración que se pasa a MaterialApp mediante el parámetro theme. Según la documentación oficial de Flutter (2026), una configuración correcta de ThemeData reduce el código de estilos duplicado en un 70–80% y garantiza una apariencia visual uniforme en todas las pantallas. El sistema de herencia incorporado permite sobrescribir el tema a nivel de widgets individuales mediante Theme.of(context).

Puntos clave

  • ThemeData — objeto de configuración con paleta de colores, tipografía y estilos de componentes
  • Theme.of(context) — acceso al tema actual desde cualquier widget mediante BuildContext
  • Light/Dark — soporte integrado para tema claro y oscuro mediante theme y darkTheme
  • Theme — widget que hereda el tema a los elementos hijo y permite sobrescribirlo
  • ColorScheme — conjunto de colores armónicos que genera estilos para todo el sistema Material

Qué son Theme y ThemeData

ThemeData es una clase que contiene la descripción completa del estilo visual de una aplicación Material. Se pasa a MaterialApp mediante el parámetro theme o darkTheme y es heredado por todos los widgets hijo. Cada widget de Material Design utiliza ThemeData para obtener sus estilos: colores de botones, tamaños de AppBar, estilos de texto, márgenes de tarjetas e iconos.

En el núcleo de ThemeData se encuentra ColorScheme, que define los colores primary, secondary, surface, error y otros. A partir de estos colores se calculan automáticamente los estados (hover, focus, pressed) para todos los componentes de Material. Por ejemplo, ElevatedButton usa el color primary para el fondo y onPrimary para el texto — sin configuración adicional.

El widget Theme es un InheritedWidget que propaga el tema hacia abajo en el árbol de widgets. Cualquier widget puede acceder al tema actual mediante Theme.of(context) y también puede crear un nuevo tema basado en el existente con valores sobrescritos mediante Theme.copyWith o ThemeData.copyWith.

En resumen: ThemeData es la fuente única de estilos de la aplicación. Comience el desarrollo definiendo ThemeData — esto establece el lenguaje visual de todo el proyecto y evita estilos dispersos en diferentes pantallas.

ColorScheme: la base de la paleta de colores

ColorScheme es el elemento central de la tematización en Material 3. Reemplaza los obsoletos primarySwatch y primaryColor, proporcionando un conjunto completo de colores para todos los estados y componentes.

ColorScheme contiene 12 colores principales: primary, onPrimary, secondary, onSecondary, surface, onSurface, error, onError, background, onBackground, outline y shadow. Para cada color se calculan automáticamente las variantes claro y oscuro, así como los colores para los estados hover, focus, pressed y dragged. Cuando solo se especifica primary, el framework genera automáticamente los colores restantes mediante ColorScheme.fromSeed.

El método ColorScheme.fromSeed (Material 3) toma un color base seedColor y genera una paleta armónica completa basada en el algoritmo de Material Design 3. Esto elimina la necesidad de seleccionar manualmente colores complementarios y análogos. Basta con pasar un color de marca principal, y ColorScheme.fromSeed crea una paleta coherente para todo el sistema Material.

En resumen: en proyectos nuevos, use ColorScheme.fromSeed para generar la paleta. Para compatibilidad con Material 2 — use primarySwatch. ColorScheme es el mínimo requerido para Material 3.

Tipografía y TextTheme: fuentes de la aplicación

TextTheme es una parte de ThemeData que define los estilos de texto para todos los niveles de encabezados, subencabezados, cuerpo y etiquetas. Material Design define 15 estilos de texto: headlineLarge, headlineMedium, headlineSmall, titleLarge, titleMedium y otros.

La tipografía se configura ya sea mediante GoogleFonts para la carga automática de fuentes, o mediante el integrado Theme.of(context).textTheme con objetos TextStyle personalizados. GoogleFonts proporciona cientos de fuentes a través del paquete google_fonts, que las almacena en caché localmente después de la primera carga. La alternativa es incrustar fuentes en los assets del proyecto mediante pubspec.yaml.

Para tipografía adaptativa, TextTheme admite MediaQuery.textScaleFactor — cuando el tamaño de fuente del sistema aumenta, todos los estilos de texto se escalan proporcionalmente. Además, se pueden establecer diferentes tamaños de fuente para diferentes factores de forma mediante isTest según MediaQuery.size.width.

En resumen: defina TextTheme en ThemeData y use Theme.of(context).textTheme para todos los elementos de texto. Esto garantiza la consistencia de las fuentes y simplifica los cambios globales de tipografía.

Herencia y sobrescritura del tema

Theme es un InheritedWidget que propaga el tema de padres a hijos. Cualquier widget hijo puede tanto leer el tema actual mediante Theme.of(context) como crear su propia copia con cambios mediante ThemeData.copyWith.

Mecanismo de herencia: si un widget está envuelto en un Theme con nuevos datos, todos sus descendientes ven el tema sobrescrito, mientras que los widgets fuera de este envoltorio ven el original. Esto permite, por ejemplo, aislar estilos para una pantalla específica: un encabezado usa un tema personalizado con un AppBarTheme modificado, mientras que el resto de la aplicación usa el estándar.

El anidamiento de Theme puede ser ilimitado. Flutter utiliza una búsqueda jerárquica: al llamar a Theme.of(context), el framework asciende por el árbol hasta el primer Theme y devuelve su tema. Si no se encuentra ningún Theme — se lanza una excepción. Por lo tanto, MaterialApp siempre envuelve la aplicación en un Theme.

En resumen: la herencia de Theme es un mecanismo flexible para aislar estilos. Use la sobrescritura del tema para pantallas individuales sin duplicar la configuración global.

Tema oscuro: modo oscuro de la aplicación

Tema oscuro es la capacidad integrada de Flutter para cambiar entre temas claro y oscuro. ThemeData se almacena en los parámetros theme (claro) y darkTheme (oscuro) de MaterialApp. El parámetro themeMode controla el modo: ThemeMode.light (siempre claro), ThemeMode.dark (siempre oscuro) o ThemeMode.system (sigue la configuración del sistema).

Al implementar un tema oscuro, no es necesario recrear todos los estilos desde cero. Simplemente pase ColorScheme.fromSeed(seedColor, brightness: Brightness.dark) a darkTheme. El framework ajustará automáticamente los colores para un fondo oscuro: surface se vuelve gris oscuro, el texto se vuelve claro. Otros subtemas (AppBarTheme, CardTheme, BottomNavigationBarTheme) se heredan de la versión clara a menos que se sobrescriban explícitamente.

Para transiciones suaves entre temas, Flutter proporciona animación mediante AnimatedTheme. Al cambiar themeMode, los colores y estilos se animan, creando una transición visualmente agradable. AnimatedTheme utiliza Duration y Curve para configurar la velocidad de la animación.

En resumen: el tema oscuro se implementa mediante darkTheme y ColorScheme.fromSeed con brightness: Brightness.dark. Use ThemeMode.system para seguir la configuración del sistema del usuario.

Ejemplos de código con Theme y ThemeData

Ejemplo 1 — configuración global del tema mediante MaterialApp usando ColorScheme.fromSeed.

dart
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 ejemplo crea un ThemeData con Material 3, un esquema de colores basado en índigo y estilos personalizados de AppBar y Card. useMaterial3 habilita el nuevo sistema de temas Material 3, y ColorScheme.fromSeed genera la paleta completa.

Ejemplo 2 — acceso al tema y sobrescritura para una parte de la aplicación.

dart
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(),
      ),
    ],
  );
}

El segundo ejemplo demuestra el uso de Theme.of(context) para leer estilos y Theme() con copyWith para sobrescribir el tema en una parte del árbol sin cambiar la configuración global. SpecialSection dentro de Theme recibirá el color primary naranja, mientras que el resto de la aplicación conserva el índigo original.

En resumen: el tema global se define en MaterialApp, se accede mediante Theme.of(context) y se sobrescribe mediante Theme con copyWith. Para Material 3, use ColorScheme.fromSeed.

Errores típicos al configurar el tema

Error 1: usar primarySwatch en lugar de ColorScheme en Material 3. primarySwatch está obsoleto y no es compatible con Material 3. Al usar useMaterial3: true con primarySwatch, Flutter emite una advertencia. Solución: migrar a ColorScheme.fromSeed para la generación de la paleta.

Error 2: codificar colores directamente en los widgets en lugar de usar Theme.of(context). Los desarrolladores escriben Colors.blue directamente en un Container en lugar del color primary o secondary del tema. Al cambiar el tema, estos colores permanecen sin cambios, rompiendo la coherencia del estilo. Solución: use siempre Theme.of(context).colorScheme.primary u otros colores del tema.

Error 3: falta de darkTheme. Si la aplicación no define darkTheme, cuando se activa el tema oscuro en el dispositivo, Flutter intenta adaptar el tema claro automáticamente, lo que a menudo da un resultado de baja calidad. Solución: siempre pase darkTheme a MaterialApp, incluso si el tema oscuro no es una prioridad — esto es importante para la experiencia del usuario.

Error 4: crear un nuevo tema en cada build. Si ThemeData se crea dentro del método build, cada reconstrucción del widget crea un nuevo objeto de tema, rompiendo la optimización de InheritedWidget. Solución: mover ThemeData a un campo static o constructor const fuera del build.

En resumen: la tematización correcta requiere un enfoque centralizado. Mueva ThemeData a constantes, use esquemas de colores del tema y siempre defina ambos temas — claro y oscuro.

Preguntas frecuentes

¿En qué se diferencia Theme de ThemeData?

ThemeData son los datos de configuración (colores, fuentes, estilos). Theme es un InheritedWidget que transmite ThemeData hacia abajo en el árbol de widgets. Theme.of(context) devuelve el ThemeData que el Theme más cercano propaga en el contexto actual.

¿Cómo cambiar el tema de la aplicación dinámicamente?

Controle themeMode en MaterialApp mediante el estado de la aplicación. Cambie el estado de ThemeMode.light a ThemeMode.dark, y Flutter reconstruirá todo el árbol con el nuevo tema. Para una animación suave, use AnimatedTheme.

¿Qué es ColorScheme.fromSeed?

ColorScheme.fromSeed es un método de Material 3 que toma un color base (seedColor) y genera una paleta armónica completa: primary, secondary, tertiary, surface, error y sus variantes on. Permite obtener un esquema de colores coherente a partir de un solo color de marca.

¿Cómo usar fuentes personalizadas con Theme?

A través de TextTheme dentro de ThemeData: especifique TextStyle con fontFamily para cada nivel. Para Google Fonts, use el paquete google_fonts, pasando fontFamily directamente a TextTheme. Para fuentes locales — inclúyalas mediante pubspec.yaml en la sección fonts.

¿Se puede sobrescribir el tema para una sola pantalla?

. Envuelva la pantalla en un Theme con datos sobrescritos mediante copyWith. Todos los widgets hijo dentro de este Theme recibirán los estilos modificados, mientras que el resto de la aplicación conserva el tema original. Esto no genera sobrecarga adicional.

Resumen

  • ThemeData — objeto de configuración con paleta de colores, tipografía y estilos de todos los componentes Material
  • ColorScheme.fromSeed — la forma principal de generar una paleta de colores en Material 3 a partir de un solo color de marca
  • Theme.of(context) — acceso al tema actual para leer estilos sin duplicar código
  • Theme — InheritedWidget para heredar y sobrescribir el tema en un subárbol de widgets
  • Tema oscuro — ThemeData separado con brightness: Brightness.dark, controlado mediante themeMode
  • Recomendación: mueva ThemeData a static o const, siempre defina theme y darkTheme en MaterialApp

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también