flutter_theme_changer_erfan 0.0.5+0 copy "flutter_theme_changer_erfan: ^0.0.5+0" to clipboard
flutter_theme_changer_erfan: ^0.0.5+0 copied to clipboard

A Flutter package that allows you to change your app's theme color dynamically with 4 beautiful widgets.

Flutter Dynamic Theme Changer #

A Flutter package that allows you to easily change your app's theme color dynamically at runtime using Riverpod.
It provides both a full theme changer wrapper and four beautiful theme widgets!

โ˜• Support #

If you find this package helpful, consider supporting my work:

Buy Me a Coffee

โœจ Features #

  • ๐ŸŽจ Dynamic primary color theme switching with Material 3 ColorScheme
  • ๐Ÿงฉ Five ready-to-use theme widgets:
    • ThemeColorPickerWidget: An expandable color picker that can be placed anywhere (Great for floating).
    • ThemeDialogButton: A convenient button that shows colors in a dialog. which is great for all common use cases.
    • CustomColorPickerDialog: A static utility to show a theme picker from any custom widget or UI element.
    • ThemeModeToggle: A simple toggle for switching between light and dark mode.
    • DarkLightModeCustomToggle: An advanced toggle for custom light/dark mode color schemes.
  • ๐ŸŒˆ Allow users to pick from customizable color palettes
  • ๐Ÿš€ Built with Flutter Riverpod 2.0 (StateNotifier based)
  • ๐ŸŽฏ Simple API and easy integration
  • โœ๏ธ Fully customizable if needed
  • โœ… Compatible with Flutter 3.24 and Material 3
  • ๐Ÿ”„ Optimized performance with background processing
  • ๐Ÿ’พ Persistent theme preferences across app restarts
  • ๐Ÿงต Off-main-thread theme generation for smooth UI

๐ŸŽฅ Theme Color Picker Demo #

ThemeColorPickerWidget

Above: Animated demo of ThemeColorPickerWidget.


๐ŸŽฅ Theme Dialog Button Demo #

ThemeDialogButton

Above: Animated demo of ThemeDialogButton widget.

Getting started #

Add this to your package's pubspec.yaml file:

dependencies:
  flutter_theme_changer_erfan: ^0.0.5+0

Then run flutter pub get to install the package.

Or run flutter pub add flutter_theme_changer_erfan in your terminal.

๐Ÿ› ๏ธ How to Use #

Basic Setup #

Wrap your app with ThemeChanger and specify a default color:

void main() {
  runApp(
    const ProviderScope(
      child: ThemeChanger(
        title: 'My App',
        defaultColor: Colors.purple, // Specify your default theme color this is required!
        scaffoldColor: Colors.white, // Optional scaffold background color
        child: HomeScreen(),
      ),
    ),
  );
}

Using ThemeDialogButton #

Add the dialog button to your AppBar for a clean theme selection experience:

AppBar(
  title: const Text('My App'),
  actions: [
    // Add the theme dialog button to your AppBar
    ThemeDialogButton(
      availableColors: [
        Colors.blue,
        Colors.red,
        Colors.green,
        Colors.orange,
        Colors.purple,
      ],
    ),
  ],
)

Using ThemeColorPickerWidget #

Place the color picker widget anywhere in your app for a floating theme selection experience:

// For ThemeColorPickerWidget
ThemeColorPickerWidget(
  availableColors: [
    Colors.teal,
    Colors.indigo,
    Colors.deepOrange,
    Colors.cyan,
    Colors.lime,
    Colors.amber,
  ],
)

// For ThemeDialogButton (coming soon)

๐ŸŽจ Custom Theme Picker Integration #

In addition to the built-in widgets, you can now trigger the theme color picker from any custom UI element using the CustomColorPickerDialog:

Basic Button Example #

ElevatedButton(
  onPressed: () => CustomColorPickerDialog.showColorPickerDialog(context),
  child: Text('Change Theme'),
)

Icon Button Example #

IconButton(
  icon: Icon(Icons.palette),
  onPressed: () => CustomColorPickerDialog.showColorPickerDialog(
    context,
    availableColors: [
      Colors.purple,
      Colors.orange,
      Colors.teal,
      Colors.pink,
      Colors.indigo,
    ],
  ),
  tooltip: 'Change Theme',
)

Custom Widget Example #

GestureDetector(
  onTap: () => CustomColorPickerDialog.showColorPickerDialog(context),
  child: Container(
    padding: EdgeInsets.all(12),
    decoration: BoxDecoration(
      color: Theme.of(context).colorScheme.primary,
      borderRadius: BorderRadius.circular(8),
    ),
    child: Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        Icon(
          Icons.format_paint,
          color: Theme.of(context).colorScheme.onPrimary,
        ),
        SizedBox(width: 8),
        Text(
          'Custom Theme Selector',
          style: TextStyle(
            color: Theme.of(context).colorScheme.onPrimary,
          ),
        ),
      ],
    ),
  ),
)

Toggle Switch Example #

bool _toggleValue = false;

Switch(
  value: _toggleValue,
  onChanged: (value) {
    setState(() {
      _toggleValue = value;
    });
    if (value) {
      CustomColorPickerDialog.showColorPickerDialog(
        context,
        availableColors: [
          Colors.purple,
          Colors.orange,
          Colors.teal,
          Colors.pink,
          Colors.indigo,
        ],
      );
    }
  },
)

From Event Handlers #

void onUserPreferenceChanged() {
  CustomColorPickerDialog.showColorPickerDialog(context);
}

This gives you complete flexibility to integrate theme changing functionality with your own UI components and interaction patterns.

Using ThemeModeToggle #

Add a simple light/dark mode toggle to your app:

void main() {
  runApp(
    const ProviderScope(
      child: ThemeChanger(
        title: 'My App',
        defaultColor: Colors.purple,
        child: HomeScreen(),
      ),
    ),
  );
}

// In your UI:
AppBar(
  title: const Text('My App'),
  actions: [
    // Add the theme mode toggle to your AppBar
    const ThemeModeToggle(
      showIcon: true,
      showText: true,
      compact: false,
    ),
  ],
)

Using DarkLightModeCustomToggle #

For advanced theming with custom color palettes for light and dark modes:

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends ConsumerStatefulWidget {
  const MyApp({super.key});

  @override
  ConsumerState<MyApp> createState() => _MyAppState();
}

class _MyAppState extends ConsumerState<MyApp> {
  @override
  void initState() {
    super.initState();
    _initializeTheme();
  }
  
  void _initializeTheme() {
    // Define custom colors for light and dark modes
    final lightModeColors = {
      'background': Colors.white,
      'card': Colors.blue.shade50,
      'primary': Colors.blue.shade600,
      'text': Colors.black87,
    };

    final darkModeColors = {
      'background': Colors.grey.shade900,
      'card': Colors.grey.shade800,
      'primary': Colors.blue.shade400,
      'text': Colors.white,
    };
    
    // Initialize custom theme colors
    CustomThemeColorPalette.initialize(
      ref,
      lightModeColors: lightModeColors,
      darkModeColors: darkModeColors,
      isDarkMode: false, // Default to light mode
      syncWithAppTheme: true,
    );
  }

  @override
  Widget build(BuildContext context) {
    return ThemeChanger(
      title: 'Custom Theme Demo',
      defaultColor: Colors.blue.shade600,
      child: HomeScreen(),
    );
  }
}

// In your UI:
AppBar(
  title: const Text('My App'),
  actions: [
    // Add the custom theme toggle to your AppBar
    Padding(
      padding: const EdgeInsets.all(8.0),
      child: DarkLightModeCustomToggle(
        lightModeColors: {
          'background': Colors.white,
          'card': Colors.blue.shade50,
          'primary': Colors.blue.shade600,
          'text': Colors.black87,
        },
        darkModeColors: {
          'background': Colors.grey.shade900,
          'card': Colors.grey.shade800,
          'primary': Colors.blue.shade400,
          'text': Colors.white,
        },
        syncWithAppTheme: true,
        defaultDarkMode: false,
      ),
    ),
  ],
)

How DarkLightModeCustomToggle Works

The DarkLightModeCustomToggle provides a powerful way to implement custom color palettes for both light and dark modes:

  1. Named Color Palettes: Define your own color maps with semantic keys like 'background', 'text', 'card', etc.

  2. Separate Light/Dark Palettes: Create distinct color sets for light and dark modes that automatically switch when toggled.

  3. App Theme Synchronization: When syncWithAppTheme is set to true, the toggle will also update the app's main theme.

  4. Accessing Colors: You can access your custom colors anywhere in your app using:

    // Create a color palette reference
    final colorPalette = CustomThemeColorPalette(ref);
       
    // Use it to get colors by name
    Container(
      color: colorPalette.getColor('background'),
      child: Text(
        'Hello World',
        style: TextStyle(color: colorPalette.getColor('text')),
      ),
    )
    
  5. Default Mode: Set defaultDarkMode to true to start your app in dark mode with the dark palette.

  6. Custom Icon Colors: Customize the toggle's appearance with lightModeIconColor and darkModeIconColor.

This approach gives you complete control over your app's color scheme while maintaining the simplicity of a single toggle for your users.

๐Ÿ“ฆ What's Inside #

Widget/File Purpose
ThemeChanger Wraps your app with dynamic theming
ThemeColorPickerWidget Expandable color picker that shows in-place
ThemeDialogButton AppBar button that shows colors in a dialog
CustomColorPickerDialog Static utility to show a theme picker from any widget
ThemeModeToggle Simple toggle for switching between light and dark mode
DarkLightModeCustomToggle Advanced toggle for custom light/dark mode color schemes
ThemeNotifier + themeProvider Riverpod logic for managing theme color

๐Ÿ“ฒ Example #

A full working example is available inside the /example folder.

To run the example locally:


flutter run --target=example/lib/main.dart

You'll see a floating color button โ€” tap it, pick a color, and the app's theme changes instantly!

โœ… All tests passed,including integration tests #

โœ… All tests passed, including integration tests #

ScreenShot of testings log

๐Ÿ™Œ Contributing #

Contributions are welcome! Feel free to open issues or submit pull requests if you'd like to help!

๐Ÿ”ฅ Author #

Erfan Alizada. Developed with โค๏ธ using Flutter and Riverpod.

Additional information #

  • For more examples, check out the example directory
  • Report bugs on the issue tracker
  • Contribute to the package on GitHub

๐Ÿ“„ License #

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for more details.

๐Ÿ” Performance Considerations #

This package is optimized for performance with:

  • Background processing for theme generation using isolates
  • Efficient state management with Riverpod
  • Minimal rebuilds when changing themes
  • Immediate UI feedback with optimized theme generation

For apps concerned with performance, you can monitor theme changes:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  
  // Add performance monitoring
  final observer = PerformanceObserver();
  WidgetsBinding.instance.addObserver(observer);
  
  runApp(const ProviderScope(child: MyApp()));
}

๐Ÿ“ฑ Material 3 Support #

This package fully supports Material 3, which is the default in Flutter 3.24+. Key features include:

  • Uses ColorScheme.fromSeed for harmonious color generation
  • Properly handles Material 3 theme properties
  • Supports the new Material 3 color system
  • Adapts to both light and dark themes

The theme picker widgets automatically adapt to your app's Material version and provide a consistent experience.

๐Ÿ”„ Theme Persistence #

Themes are automatically saved to SharedPreferences and restored when the app restarts:

  • User theme preferences persist across app sessions
  • Fast loading with optimized storage
  • Fallback to default theme when no saved preference exists

๐Ÿงต Advanced Usage #

Custom Theme Generation #

You can customize how themes are generated by extending the ThemeNotifier:

class CustomThemeNotifier extends ThemeNotifier {
  @override
  Future<void> updateThemeOffMainThread(Color primaryColor) async {
    // Your custom theme generation logic
    super.updateThemeOffMainThread(primaryColor);
  }
}

// Register your custom provider
final customThemeProvider = StateNotifierProvider<CustomThemeNotifier, ThemeData>((ref) {
  return CustomThemeNotifier();
});

Performance Monitoring #

The package includes built-in performance logging that you can use to monitor theme generation times:

import 'dart:developer' as developer;

void main() {
  // Enable detailed logging
  developer.log('Theme generation performance monitoring enabled', name: 'performance');
  
  runApp(const ProviderScope(child: MyApp()));
}

๐Ÿ“Š Technical Details #

  • Uses isolates for off-main-thread theme generation
  • Implements optimized color calculations
  • Leverages Flutter's Material 3 design system
  • Provides immediate visual feedback while processing complex themes

๐Ÿ”„ Widget Compatibility Guide #

Here's a guide on which widgets can be combined and which should be used separately:

Compatible Combinations #

โœ… ThemeColorPickerWidget + ThemeDialogButton

  • These can work well together as they both use the same theme provider. You might use the dialog in the AppBar and the picker widget elsewhere in your UI.

โœ… ThemeColorPickerWidget + ThemeModeToggle

  • These work well together as they control different aspects: one changes the color palette, the other toggles between light/dark mode.

โœ… ThemeDialogButton + ThemeModeToggle

  • Similar to above, these control different aspects of theming and can be used together.

โœ… CustomColorPickerDialog + ThemeModeToggle

  • The dialog can be triggered from custom UI while the toggle handles light/dark mode.

Incompatible Combinations #

โŒ ThemeModeToggle + DarkLightModeCustomToggle

  • Both control light/dark mode switching but in different ways. Using both will cause conflicts.

โŒ DarkLightModeCustomToggle + Any color picker widget

  • The custom toggle implements its own color palette system that may conflict with the standard color pickers.
  1. Basic Theme Control:

    • ThemeDialogButton in the AppBar
    • ThemeModeToggle in the AppBar or settings screen
  2. Advanced Theme Control:

    • ThemeColorPickerWidget as a floating widget
    • ThemeDialogButton in the AppBar
    • ThemeModeToggle in the AppBar or settings screen
  3. Custom Theme Control:

    • CustomColorPickerDialog triggered from custom UI elements
    • ThemeModeToggle for light/dark switching
  4. Fully Custom Theme System:

    • DarkLightModeCustomToggle alone, with custom color palettes for both modes
0
likes
150
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package that allows you to change your app's theme color dynamically with 4 beautiful widgets.

Repository (GitHub)
View/report issues

Topics

#theme #customization #ui #widget

Documentation

API reference

License

unknown (license)

Dependencies

cupertino_icons, flutter, flutter_riverpod, riverpod, shared_preferences

More

Packages that depend on flutter_theme_changer_erfan