Home How to use ThemeExtensions in Flutter?
Post
Cancel

How to use ThemeExtensions in Flutter?

Flutter helps develop high-quality applications for various platforms, including iOS, Android, macOS, Windows, Linux, and the Web. One key feature of the Flutter framework is its extensive system of theming. Instead of configuring each widget separately, you can set default colors, fonts, and sizes in the ThemeData class, which various widgets will use.

But usually, values provided by ThemeData aren’t sufficient, so it means that classes like AppColors or AppMargins appear. Mentioned classes are good candidates for ThemeExtensions.

What is ThemeExtension?

ThemeExtension is an interface that expands the Flutter theme system. When you extend ThemeExtension class, it ensures you implement copyWith and lerp functions. With the help of InheritedWidget (handled by Theme), those two functions provide smooth transitions when changing themes (for example, from light to dark).

How to create ThemeExtension?

As an example of ThemeExtension, we will create a class that will keep brand data (only color in this example). This class has to extend ThemeExtension abstract class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import 'package:flutter/material.dart';

class Brand extends ThemeExtension<Brand> {
  const Brand({
    required this.color,
  });

  final Color? color;

  @override
  Brand copyWith({Color? color}) {
    return Brand(
      color: color ?? this.color,
    );
  }

  @override
  Brand lerp(
    ThemeExtension<Brand>? other,
    double t,
  ) {
    if (other is! Brand) return this;

    return Brand(
      color: Color.lerp(color, other.color, t),
    );
  }
}

How to register ThemeExtension?

Next, you need to add extensions to your themes. If you use ready-to-use themes, you can use the copyWith method (like in the example) or set extensions when the ThemeData object is created. Since extensions field expects an iterable, you can add as many extensions as you want.

1
2
3
4
5
6
7
8
9
10
11
12
13
MaterialApp(
  theme: ThemeData.light().copyWith(
    extensions: [
      const Brand(color: Colors.amber),
    ],
  ),
  darkTheme: ThemeData.dark().copyWith(
    extensions: [
      const Brand(color: Colors.orange),
    ],
  ),
  home: const HomePage(),
);

How to use ThemeExtension?

Now, when you have your ThemeExtension registered, you can start using it in code. You can get it through the extension function.

1
2
3
4
5
@override
Widget build(BuildContext context) {
  final brand = Theme.of(context).extension<Brand>();
  return Container(color: brand?.color);
}

Summary

At first, this may seem convoluted, and you may think using static fields in the abstract class is better. But going with ThemeExtensions has two advantages:

  • you are coupling your theme settings with framework ones
  • thanks to the lerp function, theme changes will also animate custom colors and sizes.

Complexity: Basic

Used Flutter version: 3.7.7

This post is licensed under CC BY 4.0 by the author.

How to use FVM like a pro?

Flutter security in Fintech and banking apps