Change flutter Application Theme dynamically using “bloc”

Michael Adeyemo
3 min readJan 11, 2019

For a More recent version of this article please check here

In this tutorial, we’re going to be implementing an app which allows user to change the theme of the app from light to dark or vice versa with the bloc and flutter_bloc package, we are going to use shared_preferences to persist the chosen theme and load it on the next app launch. At the end of the tutorial, our app should look like this.

If you are not very familiar with the bloc package, i beg your indulgence to go through the official bloc package website.

Let’s get started!

Create a new flutter project and add the required dependencies to the pubspec.yaml file as shown

to keep the app simple, an overview of the lib folder would look like this.

the bloc folder is where the implementation of the bloc would be, the utils file would handle the theme data properties .

Create utils.dart

here we have the two private method _buildLightTheme and _buildDarkTheme which returns ThemeData corresponding to either light or dark theme. We also have the kLightTheme and kDarkTheme fields exposing the build methods.

Next create a bloc folder inside the lib folder, and also create the change_theme_event.dart

Here we have a ChangeThemeEvent with subclasses of DecideTheme, LightTheme and DarkTheme each corresponding to the event that will be dispatch on App start,user switching to light theme, and user switching to dark theme.

Next create the change_theme_state.dart

The ChangeThemeState class has ThemeData as property, a default constructor that requires a ThemeData property and two factory constructors which correspond to LightTheme or DarkTheme.

Next we would implement the change_theme_bloc.dart

The ChangeThemeBloc extends Bloc<ChangeThemeEvent, ChangeThemeState> which requires our class to override two methods

  1. initialState
  2. mapEventToState

The initialState is called when no event has been dispatch, so we are returning the ChangeThemeState.LightTheme to be the default state.

The mapEventToState is called every time a new event is dispatched,

if the dispatched event is LightTheme, we yield ChangeThemeState.lightTheme() and save the value of option as 0 using shared_preferences

if the dispatched event is DarkTheme, we yield ChangeThemeState.darkTheme() and save the value of option as 1 using shared_preferences

if the dispatched event is DecideTheme, we await the getOption() method which returns a Future<int> and when the future resolves, it yield ChangeThemeState.lightTheme or ChangeThemeState.darkTheme depending on its value.

finally we are using the three top method

void onLightThemeChange() => dispatch(LightTheme());
void onDarkThemeChange() => dispatch(DarkTheme());
void onDecideThemeChange() => dispatch(DecideTheme());

to expose the dispatch event.

Also notice that am using a single scoped instance of the bloc, a better approach to this is to use the BlocProvider in the flutter_bloc package,but for the case of simplicity, this will be fine.

Because this tutorial is focused on how to implement the bloc and flutter_bloc package, we wont do anything fancy in the main.dart

we are using the blocBuilder from the flutter_bloc package to listen to the change in the bloc state, the blocBuilder requires a bloc and a builder function and it rebuild itself due to the latest state yielded by the bloc.

The state themeData propety is passed to the MaterialApp.theme property, to render the chosen theme.

If you enjoyed this exercise as much as I did you can support me by ⭐️the repository, or 👏 for this story.

--

--