How to Manage Flutter Themes with ColorScheme Extensions

Introduction
Managing themes effectively is a crucial part of building a well-structured Flutter application. It ensures your app maintains a consistent look and feel while allowing easy switching between light and dark modes. The common approach to theming in Flutter is to use Theme.of(context).colorScheme.primary
, but this can feel restrictive when you want to define custom color names that better match your design system.
I recently implemented theme management in my Flutter app and, like most developers, was advised to use Theme.of(context)
. However, I wanted a more personalized, structured, and readable approach. My goals were:
To define my own color names instead of relying on generic ones like
primary
orsecondary
.To keep all theme colors separate in a structured file, similar to how I organize colors in a non-themed app.
To maintain light and dark mode variations effortlessly.
To achieve this, I used an extension on ColorScheme, which turned out to be a clean and scalable solution.
Step 1: Create a ColorScheme Extension
Here’s how I structured my extension:
import 'package:flutter/material.dart';
extension CustomColors on ColorScheme {
Color get textColor => brightness == Brightness.light
? const Color(0xff000103)
: ColorConst.whiteColor;
Color get boxColor => brightness == Brightness.light
? const Color.fromARGB(255, 160, 160, 160)
: const Color.fromARGB(255, 60, 60, 60);
Color get dialogColor => brightness == Brightness.light
? Colors.white
: const Color(0xff161a1d);
}
Step 2: Using the Custom Colors in Your App
Once the extension is created, you can use your custom colors anywhere in your app like this:
Container(
color: Theme.of(context).colorScheme.boxColor,
child: Text(
'Hello, Themed World!',
style: TextStyle(color: Theme.of(context).colorScheme.textColor),
),
)
This way, you don’t have to rely on predefined color names. Instead, you get descriptive, readable names that match your project’s color system.
Managing App Theme Data
To ensure all required theme configurations are in place before app launch, you can define them in ThemeData
. This includes button themes, scaffold background, app bar styles, and more.
Step 3: Applying Themes in MaterialApp
Finally, apply the themes in MaterialApp
:
MaterialApp(
darkTheme: ThemeData(
brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed(
brightness: Brightness.dark,
seedColor: Colors.deepPurple,
),
),
theme: ThemeData(
brightness: Brightness.light,
colorScheme: ColorScheme.fromSeed(
brightness: Brightness.light,
seedColor: Colors.deepPurple,
),
),
themeMode: ThemeMode.system,
);
This ensures that your app follows the system theme settings while keeping your theme structure well-organized.
Why This Approach is Better
✅ Custom names for colors: No need to use generic names like primary
or secondary
; define colors that make sense for your app.
✅ Keeps colors organized: All color definitions live inside the CustomColors
extension, making it easier to manage and update.
✅ Easier to read and use: Instead of Theme.of(context).colorScheme.primary
, you can use Theme.of(context).colorScheme.primaryBackground
, making the code more intuitive.
Conclusion
Managing themes in Flutter can be tricky, but using extensions on ColorScheme and well-structured ThemeData
makes it easy to keep your theme colors organized, readable, and scalable. This method helps maintain a structured approach while allowing full customization of color names and configurations.
If you found this useful, give it a try in your Flutter project and share your thoughts! How do you handle theming in your apps? Let me know in the comments. 🚀
Subscribe to my newsletter
Read articles from Ruchi Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ruchi Sharma
Ruchi Sharma
Flutter developer crafting seamless apps 🚀 | Exploring tech, design, and creativity 💡 | Sharing insights, tips, and stories to inspire and grow 🌟