ThemeExtension<T extends ThemeExtension<T> > class
abstract
An interface that defines custom additions to a ThemeData object.
Learn more about ThemeExtension on the Flutter YouTube channel.
Typically used for custom colors. To use, subclass ThemeExtension, define a number of fields (e.g. Colors), and implement the copyWith and lerp methods. The latter will ensure smooth transitions of properties when switching themes.
This sample shows how to create and use a subclass of ThemeExtension that defines two colors.
To see it in action, copy and run this code snippet on DartPad.
import 'package:flutter/scheduler.dart';
import 'package:material_ui/material_ui.dart';
/// Flutter code sample for [ThemeExtension].
@immutable
class MyColors extends ThemeExtension<MyColors> {
const MyColors({required this.brandColor, required this.danger});
final Color? brandColor;
final Color? danger;
@override
MyColors copyWith({Color? brandColor, Color? danger}) {
return MyColors(
brandColor: brandColor ?? this.brandColor,
danger: danger ?? this.danger,
);
}
@override
MyColors lerp(MyColors? other, double t) {
if (other is! MyColors) {
return this;
}
return MyColors(
brandColor: Color.lerp(brandColor, other.brandColor, t),
danger: Color.lerp(danger, other.danger, t),
);
}
// Optional
@override
String toString() => 'MyColors(brandColor: $brandColor, danger: $danger)';
}
void main() {
// Slow down time to see lerping.
timeDilation = 5.0;
runApp(const ThemeExtensionExampleApp());
}
class ThemeExtensionExampleApp extends StatefulWidget {
const ThemeExtensionExampleApp({super.key});
@override
State<ThemeExtensionExampleApp> createState() =>
_ThemeExtensionExampleAppState();
}
class _ThemeExtensionExampleAppState extends State<ThemeExtensionExampleApp> {
bool isLightTheme = true;
void toggleTheme() {
setState(() => isLightTheme = !isLightTheme);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
extensions: const <ThemeExtension<dynamic>>[
MyColors(brandColor: Color(0xFF1E88E5), danger: Color(0xFFE53935)),
],
),
darkTheme: ThemeData.dark().copyWith(
extensions: <ThemeExtension<dynamic>>[
const MyColors(
brandColor: Color(0xFF90CAF9),
danger: Color(0xFFEF9A9A),
),
],
),
themeMode: isLightTheme ? .light : .dark,
home: Home(isLightTheme: isLightTheme, toggleTheme: toggleTheme),
);
}
}
class Home extends StatelessWidget {
const Home({
super.key,
required this.isLightTheme,
required this.toggleTheme,
});
final bool isLightTheme;
final void Function() toggleTheme;
@override
Widget build(BuildContext context) {
final MyColors myColors = Theme.of(context).extension<MyColors>()!;
return Material(
child: Center(
child: Row(
mainAxisAlignment: .center,
children: <Widget>[
Container(width: 100, height: 100, color: myColors.brandColor),
const SizedBox(width: 10),
Container(width: 100, height: 100, color: myColors.danger),
const SizedBox(width: 50),
IconButton(
icon: Icon(isLightTheme ? Icons.nightlight : Icons.wb_sunny),
onPressed: toggleTheme,
),
],
),
),
);
}
}
Constructors
- ThemeExtension()
-
Enable const constructor for subclasses.
const
Properties
Methods
-
copyWith(
) → ThemeExtension< T> - Creates a copy of this theme extension with the given fields replaced by the non-null parameter values.
-
lerp(
covariant ThemeExtension< T> ? other, double t) → ThemeExtension<T> - Linearly interpolate with another ThemeExtension object.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited