[go: up one dir, main page]

ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

How to dynamically change the theme in Flutter

Norbert
3 min readJun 5, 2018

--

TLDR: I made a package which takes care of all of this, if you are interested on how it’s done keep reading.

How to do it.

Usually your entry point to the app looks like this:

If you want to change the theme of your app at compile time you can modify ThemeData. There is an attribute called Brightness which changes a bunch of colors from light to dark if set to Brightness.dark .

We want it to dynamically change that variable during runtime. We therefore introduce state to the top level widget.

Now, we have to access this state. Either by passing down a callback, writing a custom InheritedWidget or using the BuildContext to walk up the tree.

Passing down a callback is the most straight forward thing to do. But it also is the most annoying one. If the tree gets deep a lot of classes just pass the callback to its children. The logic is pretty simple though all that happens is:

  • Top widget implements a method which changes the brightness and calls setState()
  • Any child who has a reference to that method can invoke it.

An InheritedWidget would solve this problem by giving all the children access to the callback. You would still have to manage a callback, but this time there is no need to pass it all the way down.

The last viable option is searching the tree for the state. This one is pretty straight forward. We need a context to start the search, all we do is walk up the tree a search for a State which is of our type.

context.ancestorStateOfType(const TypeMatcher<YourState>());

Holding a static reference or global variable is a big no go, I won’t cover why in this post though.

Now we are be able to access and modify the Brightness on the go. The last thing is to persist the Brightness across app restarts.

Using shared preferences we can fetch the brightness before we run the app. When the brightness changes we will also have to save it there.

Because the shared preferences are asynchronous we need to await the result. The call is very fast and therefore this is not a big deal.

And we’re done! Now we can change the Theme of the app anywhere in our code.

The package

Because we as developers shouldn’t waste time re-implementing features, I made this a package!

Basically it’s exactly doing all the things I talked about above but encapsulated in one handy class.

Here is how it works:

You wrap your MaterialApp in the DynamicTheme widget. There you can specify a default brightness.

Because the brightness value is changing the colors when constructing the ThemeData you’re able to either just pass the brightness on to the ThemeData constructor and let it take care of it, or you can customize it by passing your own colors depending on the Brightness.

Last but not least, the ThemedWidgetBuilder. This is the place you usually just return the MaterialApp and pass it the theme.

And that’s it.

Now you can modify your Theme from anywhere in your code with:

DynamicTheme.of(context).setBrightness(Brightness.dark);

It will take care of saving it to the shared preferences and updating the app.

Bonus

Because I had way to much fun coding this, here is a dialog you can use for the theme switching:

--

--

ProAndroidDev
ProAndroidDev

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Norbert
Norbert

Written by Norbert

Doing crazy things with Flutter

Responses (8)