theme_provider 0.3.1 copy "theme_provider: ^0.3.1" to clipboard
theme_provider: ^0.3.1 copied to clipboard

outdated

Easy to use and customizable Theme Provider. This Widget can be used to easily provide a theme controller across the widget tree.

theme_provider #

Easy to use, customizable Theme Provider. This provides app color schemes throughout the app and automatically rebuilds the UI dynamically. You can also persist your color theme as well. Easily store and retrieve user preference without hassle. This package also provides you with several widgets that can help you to easily add theme switching abilities. Additionally you can pass option classes to store and provide data which should be associated with the current theme.

Codemagic build status Pub Package

▶️ Basic Demonstration #

Basic Usage Dialog Box
Record Record

💻 Include in your project #

dependencies:
  theme_provider: ^0.3.1

run packages get and import it

import 'package:theme_provider/theme_provider.dart';

👨‍💻 Usage #

Wrap your material app like this to use dark theme and light theme out of the box.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      child: MaterialApp(
        home: ThemeConsumer(
          child: HomePage(),
        ),
      ),
    );
  }
}

Or to provide additional themes, wrap like this:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      themes: [
        AppTheme.light(), // This is standard light theme (id is default_light_theme)
        AppTheme.dark(), // This is standard dark theme (id is default_dark_theme)
        AppTheme(
          id: "custom_theme", // Id(or name) of the theme(Has to be unique)
          data: ThemeData(  // Real theme data
            primaryColor: Colors.black,
            accentColor: Colors.red,
          ),
        ),
      ],
      child: MaterialApp(
        home: ThemeConsumer(
          child: HomePage(),
        ),
      ),
    );
  }
}

To change the theme:

 ThemeProvider.controllerOf(context).nextTheme();
 // Or
 ThemeProvider.controllerOf(context).setTheme(THEME_ID);

Access current AppTheme

 ThemeProvider.themeOf(context)

Access theme data:

 ThemeProvider.themeOf(context).data
 // or
 Theme.of(context)

Wrap each route and dialog in ThemeConsumer as well.

MaterialPageRoute(
  builder: (_) => ThemeConsumer(child: SecondPage()),
),

Note: You may wrap MaterialApp with ThemeConsumer. Then you don't have to provide ThemeConsumer on routes. However that would disable the ability to use multiple theme controllers. Also a visible flickr may occur at the start of app when the saved theme is loaded.

If you want to change the StatusBarColor when the theme changes, you can provide a onThemeChanged callback to the ThemeProvider.

Passing Additional Options #

This can also be used to pass additional data associated with the theme. Use options to pass additional data that should be associated with the theme. eg: If font color on a specific button changes according to the current theme, create a class to encapsulate the value.

Options classes must implement or extend AppThemeOptions.

  class MyThemeOptions implements AppThemeOptions{
    final Color specificButtonColor;
    MyThemeOptions(this.specificButtonColor);
  }

Then provide the options with the theme.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      themes: [
        AppTheme(
          id: "light_theme",
          data: ThemeData.light(),
          options: MyThemeOptions(Colors.blue),
        ),
        AppTheme(
          id: "light_theme",
          data: ThemeData.dark(),
          options: MyThemeOptions(Colors.red),
        ),
      ],
      child: MaterialApp(
        home: ThemeConsumer(
          child: HomePage(),
        ),
      ),
    );
  }
}

Then the option can be retrieved as,

ThemeProvider.optionsOf<MyThemeOptions>(context).specificButtonColor

💾 Persisting theme #

Saving theme #

To persist themes, simply pass saveThemesOnChange as true. This will ensure that the theme is saved to the disk.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      saveThemesOnChange: true,
       child: MaterialApp(
        home: ThemeConsumer(
          child: HomePage(),
        ),
      ),
    );
  }
}

Or manually save the current theme by just using,

ThemeProvider.controllerOf(context).saveThemeToDisk();

Loading saved theme #

defaultThemeId will always be used to determine the initial theme. (If not provided the first theme you specify will be the default app theme.) But you can manually load the previous(saved) theme by using:

 ThemeProvider.controllerOf(context).loadThemeFromDisk();

To load a previously saved theme pass loadThemeOnInit as true:

ThemeProvider(
  child: MaterialApp(
    home: ThemeConsumer(
      child: HomePage(),
    ),
  ),
  saveThemesOnChange: true,
  loadThemeOnInit: true,
)

Or to load a theme/do some task at theme controller initialization use onInitCallback. This will get called on the start.

For example, snippet below will load the previously saved theme from the disk. (if previosuly saved.)

ThemeProvider(
  child: MaterialApp(
      home: ThemeConsumer(
        child: HomePage(),
      ),
    ),
  defaultThemeId: "theme_1",
  themes: [
    AppTheme.light(id: "theme_1"),
    AppTheme.light(id: "theme_2"),
    AppTheme.light(id: "theme_3"),
  ],
  saveThemesOnChange: true,
  onInitCallback: (controller, previouslySavedThemeFuture) async {
    // Do some other task here if you need to
    String savedTheme = await previouslySavedThemeFuture;
    if (savedTheme != null) {
      controller.setTheme(savedTheme);
    }
  },
)

🎁 Additional Widgets #

Theme Cycle Widget #

IconButton to be added to AppBar to cycle to next theme.

Scaffold(
  appBar: AppBar(
    title: Text("Example App"),
    actions: [CycleThemeIconButton()]
  ),
),

Theme Selecting Dialog #

SimpleDialog to let the user select the theme. Many elements in this dialog is customizable. Remember to wrap dialog is a ThemeConsumer.

showDialog(context: context, builder: (_) => ThemeConsumer(child: ThemeDialog()))

☑️ TODO #

  • ✅ Add next theme command
  • ✅ Add theme cycling widget
  • ✅ Add theme selection by theme id
  • ✅ Add theme select and preview widget
  • ✅ Persist current selected theme
  • ✅ Add unit tests and example
  • ✅ Remove provider dependency
  • ✅ Ids for theme_providers to allow multiple theme providers
  • ✅ Add example to demostrate persistence

🐞 Bugs/Requests #

If you encounter any problems feel free to open an issue. Pull request are also welcome.

308
likes
0
pub points
94%
popularity

Publisher

unverified uploader

Easy to use and customizable Theme Provider. This Widget can be used to easily provide a theme controller across the widget tree.

Homepage

License

unknown (license)

Dependencies

flutter, shared_preferences

More

Packages that depend on theme_provider