How to create Dynamic Theme in 3 Steps in Flutter
Hello Every In this tutorial we are going to learn how to create Dynamic themes in our Flutter app. As we have seen many apps that contain this feature of night mode or you can say dark mode, so how is it created?. We are going to make different themes and let the user decide which theme they want to use.
Some of the apps that support this type of feature are the Gaana music app, Twitter app and many more. It seems very complicated but it is really easy, and there are many ways to do so today I am going to show one way but in the future, I will definitely go for another way.
If you are new to this Flutter world mak sure to watch my previous blog on ‘How to install flutter in your System’.
Step 1
Firstly we will create a simple application that will have the Drawer, AppBar and some Random Text in the body. It will be somewhat like this:-
import 'package:flutter/material.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Dynmaic Theme",
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dymanic Theme"),
),
body: Center(
child: Text("Hello World!"),
),
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text("Tap any one to change"),
),
Divider(),
ListTile(
title: Text("Light Mode"),
onTap: (){},
),
Divider(),
ListTile(
title: Text("Night Mode"),
onTap: (){},
),
Divider(),
ListTile(
title: Text("Dark Mode"),
onTap: (){},
),
],
),
),
);
}
}
Above is the code and the output of the following will be:
Step 2
Now we have to create an Inherited Widget class that will be responsible for our theme change. But before that we have to create an Enum class that will contain the data or constant values it totally depends on you if you want to make enum class or not, you can go for constant values also.
Enum class will look like this:-
enum Keys {LIGHT_MODE, NIGHT_MODE, DARK_MODE}
//In class KeysEnum.dart
Before talking about the Inherited Class I would like to talk about one more class ie MyTheme class this is the place where we keep our main code of Themes. You can keep your theme I have used very simple themes. This will go like this:-
//themesdart.dart
class MyThemes{
static final ThemeData light=ThemeData.light();
static final ThemeData night=ThemeData.dark();
static final ThemeData dark=ThemeData(
primaryColor: Colors.black,
brightness: Brightness.dark,
);
static ThemeData keyTheme(Keys obj){
switch(obj){
case Keys.LIGHT_MODE: return light;
case Keys.NIGHT_MODE: return night;
case Keys.DARK_MODE: return dark;
default: return light;
}
}
}
Now talking about the main CustomThemeClass.
This class contains Key and Data ie the Theme of our class to attach our main class with theme class. This will look like this:-
class CustomThemeClass extends InheritedWidget {
final CustomThemeState data;
CustomThemeClass({this.data, Key key, @required Widget child,}) : super(key: key, child: child);
@override
bool updateShouldNotify(CustomThemeClass oldWidget) {
return true;
}
}
class CustomTheme extends StatefulWidget {
final Widget child;
final Keys initialKey;
const CustomTheme({Key key, this.initialKey, @required this.child,}) : super(key: key);
@override
CustomThemeState createState() => new CustomThemeState();
static ThemeData of(BuildContext context) {
CustomThemeClass inherited = (context.inheritFromWidgetOfExactType(CustomThemeClass) as CustomThemeClass);
return inherited.data.theme;
}
static CustomThemeState instanceOf(BuildContext context) {
CustomThemeClass inherited = (context.inheritFromWidgetOfExactType(CustomThemeClass) as CustomThemeClass);
return inherited.data;
}
}
class CustomThemeState extends State<CustomTheme> {
ThemeData _theme;
ThemeData get theme => _theme;
@override
void initState() {
_theme = MyThemes.keyTheme(widget.initialKey);
super.initState();
}
void changeTheme(Keys key) {
setState(() {
_theme = MyThemes.keyTheme(key);
});
}
@override
Widget build(BuildContext context) {
return CustomThemeClass(
data: this,
child: widget.child,
);
}
}
Step 3
In our last step, we just have to add a function that will be called on button press and it will call the theme which we want to put.
void _changeTheme(BuildContext buildContext, MyKeys key) {
CustomTheme.instanceOf(buildContext).changeTheme(key);
}
At last, we just have to call this function with the Keys and theme. The main page will be like this:
void main(){
runApp(
CustomTheme(
initialThemeKey: MyKeys.LIGHT_MODE,
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Dynmaic Theme",
debugShowCheckedModeBanner: false,
theme: CustomTheme.of(context),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
void _changeTheme(BuildContext buildContext, MyKeys key) {
CustomTheme.instanceOf(buildContext).changeTheme(key);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dymanic Theme"),
),
body: Center(
child: Text("Hello World!"),
),
drawer: Drawer(
child: ListView(
children: <Widget>[
ListTile(
title: Text("Tap any one to change"),
),
Divider(),
ListTile(
title: Text("Light Mode"),
onTap: (){
print("Light Mode Pressed");
_changeTheme(context, MyKeys.LIGHT_MODE);
},
),
Divider(),
ListTile(
title: Text("Night Mode"),
onTap: (){
print("Night Mode Pressed");
_changeTheme(context,MyKeys.NIGHT_MODE);
},
),
Divider(),
ListTile(
title: Text("Dark Mode"),
onTap: (){
print("Dark Mode Pressed");
_changeTheme(context, MyKeys.DARK_MODE);
},
),
],
),
),
);
}
}
The output of the above-mentioned process will be:-
The source code is uploaded to my Github repository. Click here to visit my Github repo.
So, at last, we have seen how to implement a dark theme in our app, there are many ways to do so this was one method to do it, In the future, I will definitely upload blog on how to make dynamic themes using Provider and Bloc, So stay tuned.
Make sure to subscribe to my YouTube Channel :
And follow on Instagram:
@mycodecave
Also on Facebook :