Adaptive Chameleon Theme

A Flutter package that will automatically retrieve your OS defined Theme (Dynamic), force your prefered one (Light / Dark), allow you to present the user with a set of color themes to choose from and of course, persist this choice in your device.

Pub Version GitHub codecov

Features

  • Set default theme
  • Override system theme mode and set yours (light/dark)
  • Change theme colors
  • Customize color palettes for different theme modes

Demo

Click below to watch a quick demo.

Alt text

Getting started

Add the following dependency to your pubspec.yaml

dependencies:
  adaptive_chameleon_theme: <latest_version>

Usage

This package allows for an arbitrary number of themes to be defined. Each theme has a unique ID of type int. To create the themes and map them to IDs, first you have to create an instance of ThemeCollection, like so:

final themeCollection = ThemeCollection(
    themes: {
        0: ThemeData(primarySwatch: Colors.blue),
        1: ThemeData(primarySwatch: Colors.red),
    },
    fallbackTheme: ThemeData.light(), // optional fallback theme, default value is ThemeData.light()
);

I would however recommend you introduce a class with static const int values to associate a name to each ID value for easier reference:


class AppThemes {
    static const int LightBlue = 0;
    static const int LightRed = 1;
}
final themeCollection = ThemeCollection(
    themes: {
        AppThemes.LightBlue: ThemeData(primarySwatch: Colors.blue),
        AppThemes.LightRed: ThemeData(primarySwatch: Colors.red),
    },
    fallbackTheme: ThemeData.light(),
);
final darkThemeCollection = ThemeCollection(
    themes: {
        AppThemes.Blue: ThemeData(primarySwatch: Colors.blue),
        AppThemes.Red: ThemeData(primarySwatch: Colors.red),
    },
    fallbackTheme: ThemeData.dark(),
);

NOTE: Remember to define a collection of dark themes equivalent in number to the normal themes.

Proceed to wrap your MaterialApp with AdaptiveChameleonThemeWidget in order to apply and modify UI themes.

import 'package:example/themes.dart';
import 'package:flutter/material.dart';

import 'package:adaptive_chameleon_theme/adaptive_chameleon_theme.dart';

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return AdaptiveChameleonThemeWidget(
            themeCollection: AppThemes.themeCollection,
            darkThemeCollection: AppThemes.darkThemeCollection,
            defaultThemeId: AppThemes.aokiji, // optional, default id is 0
            builder: (context, theme, darkTheme, themeMode) {
              return MaterialApp(
                title: 'Flutter Demo',
                theme: theme,
                darkTheme: darkTheme,
                themeMode: themeMode,
                home: const MyHomePage(title: 'Adaptive Chameleon Theme'),
              );
            }
    );
  }
}

Changing Theme Mode

You can utilise the changeThemeMode function from anywhere in your app. It provides a simple and straight forward way of altering the theme modes: light to dark, dark to light or to system default.

This function has two optional parameters: dynamic and dark. If the value of dynamic is true, it takes precedence over dark.

  // sets theme mode to dark
  AdaptiveChameleonTheme.of(context).changeThemeMode(dark: true);
  
  // sets theme mode to light
  AdaptiveChameleonTheme.of(context).changeThemeMode(dark: false);
  
  // sets theme mode to system default
  AdaptiveChameleonTheme.of(context).changeThemeMode(dynamic: true);

Changing Theme Color

The theme can be set anywhere in the app, provided you have a BuildContext, e.g.:

  AdaptiveChameleonTheme.of(context).setTheme(AppThemes.LightRed);

By setting the theme, its ID is automatically saved via the shared_preferences package, so the next time the app starts, the theme can be restored automatically.

How to get the current theme

Current app ThemeMode

  ThemeMode themeMode = AdaptiveChameleonTheme.of(context).themeMode;  

The above example will return a value of the enum used by MaterialApp's ThemeMode with one of the following values:

system - Use either the light or dark theme based on what the user has selected in the system settings.

light - Always use the light mode regardless of system preference.

dark - Always use the dark mode (if available) regardless of system preference.

Current app ThemeId

To get the ID of the current theme, for example to create a selection UI as done in the example app provided with this package, call

  final themeId = AdaptiveChameleonTheme.of(context).themeId;

Also Included

The plugin contains some out-of-the-box widgets to make implementation easier.

ThemeModeSelectorWidget

This is a toggle buttons widget that allows you to switch theme modes.

  const ThemeModeSelectorWidget()

ThemeColorSelectorWidget

This is a toggle buttons widget that allows you to switch theme colors.

  ThemeColorSelectorWidget(
    themeCollection: AppThemes.themeCollection,
    selectedTheme: AdaptiveChameleonTheme.of(context).themeId,
  )

Example

The example app can be found in the example folder. It implements a dropdown menu to select between 5 themes. The app is the source for the video demo above.

Maintainer

If you experience any problems using this package, please create an issue on Github. Pull requests are also welcome.

Acknowledgements

Many thanks to the projects/packages below that served as inspiration for this undertaking:

Liked Adaptive Chameleon Theme?

Show some love and support by starring the repository.

Or You can