Search code examples
flutterdartmaterial-designthemes

Flutter combining text theme and direct styles


I'm writing a Material app and want to use the predefined text theme styles as much as possible rather than re-inventing typical theme elements from scratch.

So to set the text a little bigger I do this

Text('foo', style: Theme.of(context).textTheme.bodyLarge);

Which seems cool. But if I want it emphasized, there's no "bodyEmphasized" so maybe I do this

Text('foo', style: const TextStyle(fontWeight: FontWeight.bold));

But what if I want the text both bodyLarge and emphasized. There's certainly no bodyLargeEmphasized, so I tried to do this

Text('foo', style: Theme.of(context).textTheme.bodyLarge.copyWith(fontWeight: FontWeight.bold);

But this throws a null safety error because apparently bodyLarge is nullable. Huh? How could standard text theme styles be nullable?

So what do I do? Is there a simple way to make something bigger and emphasized while staying within a standard theme styles? Maybe there is a logical theme that has a set of styles like bigger and bolder that can be safely combined? If not, what's a reasonably efficient way to handle this? Do I have to code a backup plan for bodyLarge being null, and any other style element I use? If I need to do that, I might as well create my theme from scratch. Or do I just append the shriek to bodyLarge! and hope for the best?


Solution

  • Look at this statement in the source code:

    assert(
          (displayLarge == null && displayMedium == null && displaySmall == null && headlineMedium == null &&
              headlineSmall == null && titleLarge == null && titleMedium == null && titleSmall == null &&
              bodyLarge == null && bodyMedium == null && bodySmall == null && labelLarge == null && labelSmall == null) ||
          (headline1 == null && headline2 == null && headline3 == null && headline4 == null &&
              headline5 == null && headline6 == null && subtitle1 == null && subtitle2 == null &&
              bodyText1 == null && bodyText2 == null && caption == null && button == null && overline == null),
          'Cannot mix 2018 and 2021 terms in call to TextTheme() constructor.'
        );
    

    These styles are nullable because either 2018 or 2021 styles are initialized. If you use the default 2021 styles, you can safely assume that bodyLarge property is not null. Otherwise this assert statement is going to fail when you try to run your code in emulator.