Fi Li Ppo
Fi Li Ppo

Reputation: 187

How to extend ThemeData and override a property type

I am using ThemeData's "extensions" property:

ThemeData(
...
  extensions: <ThemeExtension>[
    CustomThemeExtension(
    ...
    ),
  ...
),

by looking at its definition: Iterable<ThemeExtension<dynamic>>? extensions,

which makes sense, but forces me to null check each and every use:

Text(
  carouselModel.title,
  style: themeState
    .extension<CustomTextTheme>()
    ?.h1Bold
    .copyWith(
      color: themeState
      .extension<CustomThemeExtension>()
      ?.primaryBrand,
    ),
    textAlign: TextAlign.center,
),

Is there a way to change the definition to be null safe, and get rid of all those ??

Because ThemeData is part of the framework, is immutable, and has a factory constructor, something like this will not work.

If I had control over ThemeData, I could do something like this, but nope.

I have tried extending ThemeData and @override extensions, but to no avail.

Any help will be much appreciated.

Upvotes: 0

Views: 55

Answers (2)

Altay
Altay

Reputation: 159

I didn’t fully understand your issue, but if you’re trying to bypass null-safety, you can do it this way (let’s not forget that this approach is unsafe).

ThemeData theme = ThemeData();

extension ThemeDataExtension on ThemeData {
  TextStyle get h1Bold => textTheme.titleLarge as TextStyle;
  Color get primaryBand => primaryColor;
}

// Example
Widget example(){
  final themeState = Theme.of(context);
  return Text("Hello", style: themeState.h1Bold.copyWith(color: themeState.primaryBand));
}

Addition: If your issue is only with the ? mark, you can use the ! mark instead to inform the compiler that this value will not be null. It will serve the same function as the example I provided above.

Upvotes: 1

Maoux
Maoux

Reputation: 173

You can use extension on ThemeData:

extension ThemeDataExt on ThemeData {
   ThemeExtension get ext => extension<ThemeExtension>()!;
}

Then you can use it like this:

Text(
  carouselModel.title,
  style: themeState.ext.h1Bold
    .copyWith(
      color: themeState.ext.primaryBrand,
    ),
    textAlign: TextAlign.center,
),

The ! operator casts the extension to be non-nullable, it can throw a runtime exception if the cast fails. You can maybe replace it by a ?? ThemeExtension() to use default values of your theme extension.

Upvotes: 2

Related Questions