Flutter
Theme architecture
Learn theme layers and ThemeExtension.
Theme layers
In Flutter, theme layers work like this: MaterialApp takes a ThemeData and these values propagate to all descendant widgets. Descendants access the theme via Theme.of(context). Color, typography and shape are managed from one place.
MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const HomeScreen(),
);
Custom fields with ThemeExtension
Sometimes ThemeData's fixed fields are not enough; you want to add custom values like a brand color. With ThemeExtension<T> you define your own theme field. You must implement copyWith and lerp so that Flutter can interpolate values smoothly during theme transitions.
class AppColors extends ThemeExtension<AppColors> {
final Color brand;
const AppColors({required this.brand});
@override
AppColors copyWith({Color? brand}) =>
AppColors(brand: brand ?? this.brand);
@override
AppColors lerp(AppColors? other, double t) =>
AppColors(brand: Color.lerp(brand, other?.brand, t)!);
}
Exercise Write a ThemeExtension class
Write a ThemeExtension class named AppColors. It has a brand field of type Color. Implement copyWith and lerp. In main, create an AppColors instance and print its brand color.
Show example solution
import 'package:flutter/material.dart';
class AppColors extends ThemeExtension<AppColors> {
final Color brand;
const AppColors({required this.brand});
@override
AppColors copyWith({Color? brand}) =>
AppColors(brand: brand ?? this.brand);
@override
AppColors lerp(AppColors? other, double t) =>
AppColors(brand: Color.lerp(brand, other?.brand, t)!);
}
void main() {
final colors = const AppColors(brand: Color(0xFF123456));
print(colors.brand);
}
Test yourself
-
What does ThemeExtension do?
- Changes the app's screen size
- Performs state management
- Adds custom theme fields to ThemeData
- Defines a new widget type
Show answer
Adds custom theme fields to ThemeData — ThemeExtension<T> is the standard way to add your own color or size values to ThemeData's fixed fields.
-
ThemeExtension type
class AppColors extends ThemeExtension<____> {
final Color brand;
}
Show answer
class AppColors extends ThemeExtension<AppColors> {
final Color brand;
}
-
Theme layer parts
- ThemeData
- Carries all theme values
- ThemeExtension
- Adds custom theme fields
- Theme.of(context)
- Access theme from descendant
- ColorScheme.fromSeed
- Generates palette from seed
Next lesson: Token system