Dynamic Theme with Flutter
Hello, I am Muhammet Hüseyin SALCI. I am a 4th year student at Atatürk University, Department of Computer Engineering. I am doing my internship at RyseSoft company. In this article, I will try to explain the use of Dynamic Theme with Flutter.
In recent years, most people want to have the dark theme feature in the applications we use on the computer or phone. In this article, we will discuss the dynamic theme method, which will make our work much easier when adding the dark theme feature to a flutter project. Thanks to this method, it will be much easier to change the color or text style of the interconnected sections within the project.
We will be using the provider package. Add the provider plugin to pubspec.yaml file.
dependencies:
provider: ^6.0.3First of all, we will create 2 different themes for the dark theme and the light theme.
Dark Theme:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';final darkThemeData = ThemeData(
colorScheme: _appColorScheme,
textTheme: textTheme(),
appBarTheme: ThemeData.dark().appBarTheme.copyWith(
color: _appColorScheme.primary,
systemOverlayStyle: SystemUiOverlayStyle.dark,
elevation: 0,
iconTheme: IconThemeData(
color: _appColorScheme.onSecondary,
size: 21,
)),
scaffoldBackgroundColor: _appColorScheme.background,
highlightColor: _appColorScheme.primaryContainer,
floatingActionButtonTheme:
ThemeData.dark().floatingActionButtonTheme.copyWith(),
buttonTheme: ThemeData.dark().buttonTheme.copyWith(
colorScheme: const ColorScheme.dark(
onError: Color(0xffFF2D55),
),
),
);
Light Theme:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';final lightThemeData = ThemeData(
colorScheme: _appColorScheme,
textTheme: textTheme(),
appBarTheme: ThemeData.light().appBarTheme.copyWith(
color: _appColorScheme.primary,
systemOverlayStyle: SystemUiOverlayStyle.light,
elevation: 0,
iconTheme: IconThemeData(
color: _appColorScheme.onSecondary,
size: 21,
)),
scaffoldBackgroundColor: _appColorScheme.background,
highlightColor: _appColorScheme.primaryContainer,
floatingActionButtonTheme:
ThemeData.light().floatingActionButtonTheme.copyWith(),
buttonTheme: ThemeData.light().buttonTheme.copyWith(
colorScheme: const ColorScheme.light(
onError: Color(0xffFF2D55),
),
),
);
We create TextTheme and ColorScheme structures for both themes. Here I made arrangements according to my own tastes. If you want, you can change the colors and text styles and make them suitable for your own project.
Get RyseSoft’s stories in your inbox
Join Medium for free to get updates from this writer.
Dark Theme:
TextTheme textTheme() {
return const TextTheme(
headlineLarge: TextStyle(
fontSize: 36, fontWeight: FontWeight.w300, letterSpacing: -1.5),
headlineMedium: TextStyle(
fontSize: 32, fontWeight: FontWeight.w300, letterSpacing: -0.5),
headlineSmall: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
),
bodyLarge: TextStyle(
fontSize: 20,
),
bodyMedium: TextStyle(
fontSize: 18,
),
bodySmall: TextStyle(
fontSize: 15,
),
);
}ColorScheme get _appColorScheme {
return const ColorScheme(
primary: Color(0xff263340),
primaryContainer: Color(0xffBBBBBB),
secondary: Color(0xff263340),
secondaryContainer: Colors.blue,
surface: Color.fromARGB(255, 0, 0, 0),
onPrimary: Color.fromARGB(255, 241, 239, 239),
onSecondary: Color.fromARGB(255, 255, 255, 255),
onSurface: Color.fromARGB(255, 255, 255, 255),
onError: Colors.orange,
onBackground: Color.fromARGB(255, 255, 255, 255),
background: Color(0xff14212b),
error: Color(0xffeb5757),
brightness: Brightness.dark,
);
}
Light Theme:
TextTheme textTheme() {
return const TextTheme(
headlineLarge: TextStyle(
fontSize: 36, fontWeight: FontWeight.w300, letterSpacing: -1.5),
headlineMedium: TextStyle(
fontSize: 32, fontWeight: FontWeight.w300, letterSpacing: -0.5),
headlineSmall: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
),
bodyLarge: TextStyle(
fontSize: 20,
),
bodyMedium: TextStyle(
fontSize: 18,
),
bodySmall: TextStyle(
fontSize: 15,
),
);
}ColorScheme get _appColorScheme {
return const ColorScheme(
primary: Colors.blue,
primaryContainer: Color(0xffBBBBBB),
secondary: Color.fromRGBO(187, 222, 251, 1),
secondaryContainer: Colors.blue,
surface: Color.fromARGB(255, 0, 0, 0),
onPrimary: Color(0xff2B2727),
onSecondary: Color.fromARGB(255, 255, 255, 255),
onSurface: Colors.blue,
onError: Colors.orange,
onBackground: Color.fromARGB(255, 255, 255, 255),
background: Color.fromARGB(255, 255, 255, 255),
error: Color(0xffeb5757),
brightness: Brightness.light,
);
}
When the themes are ready, we create a theme notifier class to notify us of a theme change.
If you want the default theme to be dark theme when the project is started, you can change the part that says
lightThemeDarktodarkThemeData
import 'package:flutter/material.dart';
import 'package:flutter_application_2/dark_theme.dart';
import 'package:flutter_application_2/light_theme.dart';class CustomThemeDataModal extends ChangeNotifier {
ThemeData _themeData=lightThemeData;ThemeData get getThemeData => _themeData;void setThemeData(ThemeData data) {
_themeData = data;
notifyListeners();
}
}
We edit the main.dart file and wrap our project with ChangeNotifierProvider, then we get the selected theme information with CustomThemeDataModal.
void main() {
runApp(MultiProvider(providers: [
ChangeNotifierProvider(
create: (context) => CustomThemeDataModal(),
),
], child: const MyApp()));
}class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Dynamic Theme',
theme: Provider.of<CustomThemeDataModal>(context).getThemeData,
home: const MyHomePage(title: 'Flutter Dynamic Theme'),
);
}
}
Theme creation/editing processes are finished. Now we will use the themes we created in the project. For this, we add 2 ElevatedButtons.
The first of the buttons will allow us to switch to the dark theme, and the second will allow us to switch to the light theme.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Provider.of<CustomThemeDataModal>(context, listen: false)
.setThemeData(darkThemeData);
},
child: Text("Dark")),
ElevatedButton(
onPressed: () {
Provider.of<CustomThemeDataModal>(context, listen: false)
.setThemeData(lightThemeData);
},
child: Text("Light")),
],
),
),
);
}That’s it. Let’s see what the app looks like:
Author: Muhammet Hüseyin SALCI







