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.

4.2 (12) · 2 Reviews

Download materials
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

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. :]

Text Style

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! :]

Dark theme

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:

  1. You convert MyApp from a stateless to a stateful widget.
  2. Since you need ChangeNotifier to let you know when the theme changes, you subscribe to it in initState and listen to changes from currentTheme. You need to trigger a widget rebuild, so you call setState with nothing particular inside the closure.
  3. The default theme.
  4. The dark theme.
  5. Based on this attribute, MaterialApp knows which theme to apply: either theme or darkTheme.

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!

Dynamic Theme

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!