ThemData(colorScheme: xxx) vs ThemeData.from(colorScheme: xxx)?

In Chapter 2, Hello, Flutter, Section, Styling your app, we theme our app like this:

@override
Widget build(BuildContext context) {
  final ThemeData theme = ThemeData();
  return MaterialApp(
    title: 'Recipe Calculator',
    theme: theme.copyWith(
        colorScheme: theme.colorScheme.copyWith(
            primary: Colors.grey,
            secondary: Colors.black,
        ),
    ),
    home: const MyHomePage(title: 'Recipe Calculator'),
  );
}

Not liking the creation of an intermediate variable, theme, I changed it as follows:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Recipe Calculator',
      theme: ThemeData(
        colorScheme: Theme.of(context).colorScheme.copyWith(
              primary: Colors.grey,
              secondary: Colors.black,
            ),
      ),
      home: const MyHomePage(title: 'Recipe Calculator'),
    );
  }

So far so good—no visual differences. However, rather than using the ThemeData() constructor, my first attempt was instead using ThemeData.from(), like this:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Recipe Calculator',
      theme: ThemeData.from(
        colorScheme: Theme.of(context).colorScheme.copyWith(
              primary: Colors.grey,
              secondary: Colors.black,
            ),
      ),
      home: const MyHomePage(title: 'Recipe Calculator'),
    );
  }

The results, however, are not the same. When using ThemeData.from(), the background color of the screen is blue, whereas when using ThemeData(), the background is white.

The documentation for ThemeData.from() states:

Create a ThemeData based on the colors in the given colorScheme…

Whereas, the documentation of ThemeData() constructor does not specifically mention anything about the colorScheme other than that Material components use it. Not getting into the documentation, one would logically guess that the constructor ought to create a ThemeData instance with its colors in the given colorScheme, just like ThemeData.from() does.

So I fail to understand the difference.

Can someone shed some light on when to prefer one of these constructors over the other?

@salmankhilji thanks for the interesting question.

By diving into the ThemeData documentation and implementation here is the reason why the background color is blue vs white in some cases.

Using ThemeData Constructor

When you used the ThemeData constructor:

ThemeData(
        colorScheme: Theme.of(context).colorScheme.copyWith(
              primary: Colors.grey,
              secondary: Colors.black,
            ),
      ),

By default scaffoldBackgroundColor takes the canvasColor as shown below:

Screen Shot 2021-10-17 at 1.51.47 PM

This is why the background color is set to grey[50] (Almost white looking)

Using ThemeData.from

In the case when you changed to use the ThemeData.from

ThemeData.from(
        colorScheme: Theme.of(context).colorScheme.copyWith(
              primary: Colors.grey,
              secondary: Colors.black,
            ),
      ),

What you did here was:

  1. Take the existing colorScheme from the context, and create a new copy but only set primary and secondary color.

The reason why the background is light blue in this case is because the default background color uses primarySwatch which is set to blue by default. You will have to update the colorScheme’s background color in this case.

Here is a screenshot of the ThemeData constructor:

Screen Shot 2021-10-17 at 1.50.09 PM

You will notice that the default colorScheme’s backgroundColor is also set to blue.

When you look at the ThemeData.from constructor, you will see it uses colorScheme.background to set the scaffoldBackgroundCOlor

Screen Shot 2021-10-17 at 2.09.35 PM

You can check out the entire ThemeData constructor implementation here:

Hope this is helpful!

Thanks for theme Colour data solution.

myccpay