Theming your App in Flutter using BLoc, Save & Reload

By | December 6, 2020

In this article, we will see how we can use BLoc to Theme your app in Flutter.

To understand BLoC with a real world example, you can refer to my previous post on BLoC here.
Part 1

Part 1

For this demo also we will need the below plugins

flutter_bloc: ^6.0.4
equatable: ^1.2.4

If you follow my previous tutorial, it would be easy for you to understand this article as well. It’s quite similar.
Let’s create the themes for our App.
We have two themes here…

  • Dark Theme
  • Light Theme

Let’s create a new class named ‘app_themes.dart’ and declare our themes.

import 'package:flutter/material.dart';
class AppThemes {
  static final appThemeData = {
    AppTheme.lightTheme: ThemeData(
      scaffoldBackgroundColor: Colors.white,
      primarySwatch: Colors.blue,
      backgroundColor: Colors.white,
      textTheme: TextTheme(
        bodyText1: TextStyle(
          color: Colors.black,
        ),
      ),
    ),
    AppTheme.darkTheme: ThemeData(
      scaffoldBackgroundColor: Colors.black,
      primarySwatch: Colors.teal,
      backgroundColor: Colors.black,
      textTheme: TextTheme(
        bodyText1: TextStyle(
          color: Colors.white,
        ),
      ),
    )
  };
}
enum AppTheme {
  lightTheme,
  darkTheme,
}

You can see we have different colors for different properties of each theme.
We need three things here

  • Bloc
  • Events
  • State

The Bloc will accept an event and a state and output a new State.
Here we are going to update the App’s Theme, so we will add a Theme Change Event, with a Current State and we will get a new State which is a new Theme. So that’s the whole idea.
So let’s create the Event first
We have only one event here

class ThemeEvent {
  final AppTheme appTheme;
  ThemeEvent({this.appTheme});
}

Now the State,

class ThemeState {
  final ThemeData themeData;
  ThemeState({this.themeData});
}

and finally the BLoC

class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
  //
  ThemeBloc()
      : super(
          ThemeState(
            themeData: AppThemes.appThemeData[AppTheme.lightTheme],
          ),
        );
@override
  Stream<ThemeState> mapEventToState(ThemeEvent event) async* {
    if (event is ThemeEvent) {
      yield ThemeState(
        themeData: AppThemes.appThemeData[event.appTheme],
      );
    }
  }
}

Here you can see that we are sending an Initial State to the super class which is the

ThemeState(themeData: AppThemes.appThemeData[AppTheme.lightTheme])

and in the mapEventToState, when a ThemeEvent is triggered by the user, we will return a new ThemeState. Let’s see how we can do that.

AppTheme selectedTheme =
        darkTheme ? AppTheme.lightTheme : AppTheme.darkTheme;
context.bloc<ThemeBloc>().add(ThemeEvent(appTheme: selectedTheme));

Here comes the important part…

BlocProvider(
      create: (context) => ThemeBloc(),
      child: BlocBuilder<ThemeBloc, ThemeState>(
        builder: (BuildContext context, ThemeState themeState) {
          return MaterialApp(
            title: 'Flutter Bloc Demo',
            debugShowCheckedModeBanner: false,
            theme: themeState.themeData,
            home: AlbumsScreen(),
          );
        },
      ),
    );

You have to wrap your screen or widget which you want to apply theme. Here it will be our root widget. In the above code ‘AlbumsScreen’ is the home screen and our root widget is the Material Widget.
Here

theme: themeState.themeData,

is the new Theme when user triggers a Light or Dark theme.

So when ever we update the theme by calling the below code, the above widget will be triggered.
And in the rest of the app, we can use the these like this.

backgroundColor: Theme.of(context).backgroundColor,

For example,

if you want to create a Text widget that has the theme applied, It would look like this

import 'package:flutter/material.dart';
class Txt extends StatelessWidget {
  final String text;
  Txt({
    this.text = '',
  });
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text(
        text,
        style: TextStyle(
          fontSize: 20,
          color: Theme.of(context).textTheme.bodyText1.color,
        ),
      ),
    );
  }
}

Where ever you use the above widget will have the proper theme applied.

Complete Source Code

https://bitbucket.org/vipinvijayan1987/tutorialprojects/src/BlocSimple/

One thought on “Theming your App in Flutter using BLoc, Save & Reload

  1. Карина

    Hot reload doesn’t work when enumerated types are changed to regular classes or regular classes are changed to enumerated types.

    Reply

Leave a Reply to Карина Cancel reply

Your email address will not be published. Required fields are marked *