Theming a Flutter App: Getting Started
Learn how to make your app stand out by styling widgets, creating a dynamic theme, and toggling between available themes. By Andres Torres.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Theming a Flutter App: Getting Started
15 mins
Theming Text Widgets
Text widgets are special because ThemeData
gives you multiple text styles to choose from. To see this in action, change the text widget that reads “You’ve done x activities in total” in lib/home/home_page.dart to the following:
Text(
'You\'ve done $totalActivities activities in total',
style: Theme.of(context).textTheme.headline6,
),
Build and run, and you now have a nice big heading to look at. :]
Feel free to explore the different text styles contained in the TextTheme
object. You’ll see text styles broken down into headline
, subtitle
, and body
groupings. You can use these groupings to apply consistent text styles throughout your applications. This can help you create a more consistent looking application with very little effort.
Creating a Dark Theme
Nowadays, most operating systems and apps have a dark theme to use in low-light environments or to simply to give a stylistic twist to your app. You want to add this great addition to the user experience to your app as well.
To do this, open lib/theme/custom_theme.dart and add the following below lightTheme:
static ThemeData get darkTheme {
return ThemeData(
primaryColor: CustomColors.darkGrey,
scaffoldBackgroundColor: Colors.black,
fontFamily: 'Montserrat',
textTheme: ThemeData.dark().textTheme,
buttonTheme: ButtonThemeData(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18.0)),
buttonColor: CustomColors.lightPurple,
)
);
}
This block may look complex, but it’s basically the same structure that you used for lightTheme
. The difference is that the colors and styles you’re using make more sense as a dark theme.
To see this in action, open lib/main.dart and replace the theme
attribute with your new dark theme:
return MaterialApp(
title: 'Knight and Day',
home: HomePage(),
theme: CustomTheme.darkTheme,
);
Here, you’re simply passing CustomTheme.darkTheme
instead of CustomTheme.lightTheme
.
Build and run your app to see how your UI gets a beautiful revamp! :]
This is a great upgrade, but wouldn’t it be better if the user could change the theme by clicking a button? You’ll tackle that in the next section.
Toggling Between Themes
To toggle between themes, you need to keep track of the current theme. You’ll do this by creating a global instance of your theme and applying it whenever you need it. Start by creating config.dart in lib/theme and adding the following:
import 'package:knight_and_day/theme/custom_theme.dart';
CustomTheme currentTheme = CustomTheme();
This will be the instance of the custom theme you’ll use throughout the app.
Next, open lib/theme/custom_theme.dart and add the following code to the top of CustomTheme
:
static bool _isDarkTheme = true;
ThemeMode get currentTheme => _isDarkTheme ? ThemeMode.dark : ThemeMode.light;
void toggleTheme() {
_isDarkTheme = !_isDarkTheme;
notifyListeners();
}
Two main things are happening here. First, you declared a private variable that tracks whether the current theme is dark and you map _isDarkTheme
to its corresponding ThemeMode
.
Second, you create a method that toggles _isDarkTheme
and then notifies anyone who’s listening. To be able to call notifyListeners
, you need to implement ChangeNotifier
. Do this by changing CustomTheme
‘s signature to the following:
class CustomTheme with ChangeNotifier {
...
}
Now, open lib/main.dart and replace its contents with the following code. Remember to import lib/theme/config.dart:
import 'package:flutter/material.dart';
import 'package:knight_and_day/home/home_page.dart';
import 'package:knight_and_day/theme/config.dart';
import 'package:knight_and_day/theme/custom_theme.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key key}): super(key: key);
//1
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
void initState() {
super.initState();
currentTheme.addListener(() {
//2
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Knight and Day',
home: HomePage(),
theme: CustomTheme.lightTheme, //3
darkTheme: CustomTheme.darkTheme, //4
themeMode: currentTheme.currentTheme, //5
);
}
}
Here’s a breakdown of what’s happening:
- You convert
MyApp
from a stateless to a stateful widget. - Since you need
ChangeNotifier
to let you know when the theme changes, you subscribe to it ininitState
and listen to changes fromcurrentTheme
. You need to trigger a widget rebuild, so you callsetState
with nothing particular inside the closure. - The default theme.
- The dark theme.
- Based on this attribute,
MaterialApp
knows which theme to apply: eithertheme
ordarkTheme
.
The last step to make all this work is to toggle the theme by pressing the action button on the app bar. Open lib/custom_app_bar.dart and replace IconButton
with the following:
IconButton(
icon: const Icon(Icons.brightness_4),
onPressed: () => currentTheme.toggleTheme(),
)
Here you added onPressed
, a function that toggles between the different themes.
Remember to import lib/theme/config.dart:
import 'package:knight_and_day/theme/config.dart';
Now, you can build and run. Press the action button on the app bar and you’ll see how your theme changes dynamically. Great job!
Where to Go From Here?
You can download the final version of this project using the Download Materials button at the top or bottom of this tutorial.
Congratulations on making your app shine with these beautiful themes! Now, you can leverage the theming system in Flutter to elevate your apps to new levels. Great design and user experience are key when trying to engage with users.
If you want to dive a bit deeper into the world of Flutter, check out Your First Flutter App. Another great resource is our awesome book, Flutter Apprentice.
If you have any questions, comments or want to show off great theming options for your app, feel free to join the discussion below!