Control Your Flutter App Theme with Adaptive Theme Package

Control Your Flutter App Theme with Adaptive Theme Package

Written and reviewed by: 

SHARE

While developing a Flutter application, one of the key approaches in the building of beautiful and consistent user experiences is to customize the theme. It sets colors, fonts, and styles of buttons and other UI elements to specific aesthetics. Light and dark theme support can be provided by the Flutter framework using built-in means, but effectively managing these themes across an application can be a very challenging task. Here comes the adaptive_theme package.

The following post will demonstrate the smooth management of your Flutter app theme using the package adaptive_theme. We will go through the installation to the practical implementation of this package so that you know how to take advantage of it for adaptive theming. You will exactly learn how to enable smooth transitions between Light and Dark themes, store user preferences, and ultimately create dynamic looks and feels of an application.

Table of Contents

1. Introduction to Adaptive Theme

The adaptive_theme package is a powerful Flutter library that helps you manage light and dark themes efficiently. It allows you to:

  • Switch between light and dark themes programmatically.
  • Save the theme preferences (light, dark, or system default) for the user.
  • Automatically apply the system’s default theme (based on the device’s settings).

This package is designed to be simple to integrate while offering enough flexibility to suit various needs.

2. Why Use Adaptive Theme?

Flutter provides built-in support for theming through ThemeData and MaterialApp, but there are certain limitations:

  • You need to manually control the switching between light and dark themes.
  • Saving the user’s theme preference and applying it across the app requires extra work.

The adaptive_theme package simplifies these tasks by handling theme switching and saving preferences, making it ideal for apps that require a dynamic look or theme customization options.

3. Setting Up Adaptive Theme

To get started, you first need to add the adaptive_theme package to your project. Follow these steps:

Step 1: Add Adaptive Theme to pubspec.yaml
 

Open your pubspec.yaml file and add the adaptive_theme package:

				
					dependencies:
  flutter:
    sdk: flutter
  adaptive_theme: ^3.6.0

				
			

Then, run the following command to install the package:

				
					flutter pub get
				
			
Step 2: Import the Package
 

After installing, you need to import the package in your Dart file:

				
					import 'package:adaptive_theme/adaptive_theme.dart';

				
			

Now, you are ready to integrate the package into your app.

4. Integrating Adaptive Theme into Your App

To use adaptive_theme, you’ll need to wrap your app with the AdaptiveTheme widget and set up light and dark theme data.

Step 1: Wrap the App with Adaptive Theme
 

In your main.dart file, wrap the MaterialApp widget with AdaptiveTheme, like this:

				
					void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AdaptiveTheme(
      light: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
      ),
      dark: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.blue,
      ),
      initial: AdaptiveThemeMode.system, // Use system theme initially
      builder: (theme, darkTheme) => MaterialApp(
        title: 'Adaptive Theme Demo',
        theme: theme,
        darkTheme: darkTheme,
        home: HomeScreen(),
      ),
    );
  }
}

				
			

Here’s a breakdown of the key properties:

  • light: Defines the theme data for the light mode.
  • dark: Defines the theme data for the dark mode.
  • initial: Sets the initial theme mode (light, dark, or system).
Step 2: Switch Between Themes
 

The adaptive_theme package provides a simple way to switch between themes. For example, you can add a button in your app to toggle between light and dark themes:

				
					class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Adaptive Theme Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            AdaptiveTheme.of(context).toggleThemeMode();
          },
          child: Text('Toggle Theme'),
        ),
      ),
    );
  }
}

				
			

The toggleThemeMode method will switch between light and dark themes automatically.

5. Saving and Restoring Theme Preferences

The adaptive_theme package makes it easy to persist the user’s theme preferences. When a theme is changed, it is automatically saved, and the app will remember the last chosen theme even if it’s restarted.

To restore the saved theme, use AdaptiveTheme.getThemeMode() during app initialization:

				
					void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final savedThemeMode = await AdaptiveTheme.getThemeMode();
  runApp(MyApp(initialThemeMode: savedThemeMode));
}

class MyApp extends StatelessWidget {
  final AdaptiveThemeMode? initialThemeMode;

  MyApp({this.initialThemeMode});

  @override
  Widget build(BuildContext context) {
    return AdaptiveTheme(
      light: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.blue,
      ),
      dark: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.blue,
      ),
      initial: initialThemeMode ?? AdaptiveThemeMode.system,
      builder: (theme, darkTheme) => MaterialApp(
        title: 'Adaptive Theme Demo',
        theme: theme,
        darkTheme: darkTheme,
        home: HomeScreen(),
      ),
    );
  }
}

				
			

6. Listening for Theme Changes

Sometimes, you may need to perform certain actions when the theme changes. You can listen for theme changes by using AdaptiveThemeManager:
 
				
					AdaptiveTheme.of(context).addListener(() {
  final themeMode = AdaptiveTheme.of(context).mode;
  // Perform actions based on themeMode
});

				
			

This allows you to react to theme changes dynamically within the app.

7. Using Custom Themes

You can define your custom light and dark themes to give your app a unique look. For instance, you might want to create a custom color scheme and typography:

				
					final ThemeData customLightTheme = ThemeData(
  brightness: Brightness.light,
  primaryColor: Colors.teal,
  accentColor: Colors.orange,
  textTheme: TextTheme(
    bodyText1: TextStyle(color: Colors.black, fontSize: 16),
  ),
);

final ThemeData customDarkTheme = ThemeData(
  brightness: Brightness.dark,
  primaryColor: Colors.deepPurple,
  accentColor: Colors.pink,
  textTheme: TextTheme(
    bodyText1: TextStyle(color: Colors.white, fontSize: 16),
  ),
);

				
			

Then, use these custom themes in the AdaptiveTheme configuration:

				
					AdaptiveTheme(
  light: customLightTheme,
  dark: customDarkTheme,
  initial: AdaptiveThemeMode.system,
  builder: (theme, darkTheme) => MaterialApp(
    title: 'Custom Theme Demo',
    theme: theme,
    darkTheme: darkTheme,
    home: HomeScreen(),
  ),
);

				
			

8. Handling System Theme Changes

By setting the initial parameter to AdaptiveThemeMode.system, the app can automatically follow the device’s theme setting. For example, if the user enables the dark mode on their device, the app will switch to the dark theme:

				
					AdaptiveTheme(
  light: ThemeData(
    brightness: Brightness.light,
  ),
  dark: ThemeData(
    brightness: Brightness.dark,
  ),
  initial: AdaptiveThemeMode.system,
  builder: (theme, darkTheme) => MaterialApp(
    title: 'System Theme Demo',
    theme: theme,
    darkTheme: darkTheme,
    home: HomeScreen(),
  ),
);

				
			

9. Best Practices for Adaptive Theming

Here are some best practices to follow when using adaptive theming in your Flutter app:

1. Define Consistent Themes
 

Make sure that both the light and dark themes have a consistent style, with matching primary and secondary colors, fonts, and button styles.

2. Use System Settings
 

Always provide an option for the app to follow the system’s theme settings. This helps users who prefer their apps to adapt based on their device’s configuration.

3. Test Across Different Devices
 

Test the app on both Android and iOS devices to ensure that the adaptive theming works as expected.

4. Handle Theme Changes Gracefully
 

If your app changes its theme based on user actions (like tapping a button), ensure that the transition feels smooth without sudden changes.

10. Conclusion

The adaptive_theme package offers an easy-to-use and flexible solution for managing app themes in Flutter. It handles theme switching, saving preferences, and following system settings seamlessly. By using this package, you can give your Flutter app a modern, dynamic appearance and make it more user-friendly.

Whether you’re building a simple app or a complex application with extensive theming requirements, adaptive_theme is a valuable tool for Flutter developers. With just a few lines of code, you can enhance the look and feel of your app, making it adaptable to user preferences and system settings.

Now that you understand how to use the adaptive_theme package, try integrating it into your own projects and see the difference it makes in controlling your app’s theme!

>>Check out more Flutter Blogs Click Here 

FAQ

Currently, adaptive_theme does not offer built-in support for custom animations when switching themes. However, you can create your own animations by wrapping your widgets in transition effects or animations to make theme changes smoother.

To reset the theme to the system default, use AdaptiveTheme.of(context).setSystem(). This command will apply the device’s current theme setting, whether light or dark.

Yes, you can retrieve the current theme mode by using AdaptiveTheme.of(context).mode. This will return the active theme mode (light, dark, or system), which you can then use to adjust the UI accordingly.

 adaptive_theme primarily supports light, dark, and system themes. If you want additional color schemes, you might consider building custom theme logic and toggles outside the  adaptive_theme package or use multiple custom ThemeData variations with conditional statements.

 adaptive_theme automatically saves theme preferences locally, but to confirm, you can retrieve the saved mode using await AdaptiveTheme.getThemeMode(). This method will return the saved theme mode (if any), allowing you to verify its persistence.

While  adaptive_theme doesn’t include time-based theme switching, you can implement a manual time-based theme change by checking the system time and using AdaptiveTheme.of(context).setThemeMode(AdaptiveTheme.dark) or .light depending on the time of day.

You can check if the app is in dark mode by using AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark. This allows you to apply specific UI adjustments if the app is in dark mode.

Yes, but you’ll need to manually apply color properties to your custom widgets based on the theme. You can access the current theme data by calling AdaptiveTheme.of(context).theme for light mode and .darkTheme for dark mode.

If you remove  adaptive_theme, the saved preference will no longer be accessible in the app, as it relies on the package’s API. However, you can manually migrate the saved theme preferences if needed by retrieving the preference and saving it elsewhere before removal.

While  adaptive_theme is designed for app-wide theming, you can create unique themes for specific screens by applying a new ThemeData to each screen’s widget tree. However, this may conflict with the main app theme if not managed carefully.

Written and reviewed by

Picture of Muhammad Naeem
Muhammad Naeem
Professional Flutter Developer
Scroll to Top