App Theme Picker
A beautiful and customizable Flutter package for theme selection with support for multiple color schemes and theme modes (light, dark, system). Built with Flutter Riverpod for state management and FlexColorScheme for beautiful color schemes.
Features
✨ Beautiful Theme Selection UI: Elegant interface for picking color schemes
🎨 Multiple Color Schemes: Support for all FlexColorScheme color schemes
🌙 Theme Mode Support: Light, Dark, and System theme modes
💾 Persistent Settings: Theme preferences are saved automatically
🌍 Internationalization: Built-in localization support (English, Japanese, Korean, Chinese)
⚡ State Management: Powered by Flutter Riverpod for reactive state management
🎯 Customizable: Configurable button sizes and available color schemes
Screenshots
The theme picker provides an intuitive interface with:
- Theme mode buttons (Light/Dark/System) at the top
- Grid of colorful theme buttons showing available color schemes
- Real-time preview of selected themes
- Persistent theme selection across app restarts
Installation
Add this package to your pubspec.yaml:
dependencies:
app_theme_picker: ^0.0.1
Then run:
flutter pub get
Dependencies
This package requires the following dependencies (automatically installed):
flutter_riverpod: ^2.6.1- State managementflex_color_scheme: ^8.2.0- Beautiful color schemeseasy_localization: ^3.0.7- Internationalizationriverpod_helper: ^0.0.3- Riverpod utilities
Quick Start
1. Basic Setup
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:app_theme_picker/app_theme_picker.dart';
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final themeAsync = ref.watch(themePodProvider);
final themeModeAsync = ref.watch(themeModePodProvider);
return MaterialApp(
title: 'Theme Picker Demo',
theme: themeAsync.when(
data: (flexScheme) => FlexThemeData.light(scheme: flexScheme),
loading: () => FlexThemeData.light(scheme: FlexScheme.sakura),
error: (_, __) => FlexThemeData.light(scheme: FlexScheme.sakura),
),
darkTheme: themeAsync.when(
data: (flexScheme) => FlexThemeData.dark(scheme: flexScheme),
loading: () => FlexThemeData.dark(scheme: FlexScheme.sakura),
error: (_, __) => FlexThemeData.dark(scheme: FlexScheme.sakura),
),
themeMode: themeModeAsync.when(
data: (mode) => mode,
loading: () => ThemeMode.light,
error: (_, __) => ThemeMode.light,
),
home: HomeScreen(),
);
}
}
2. Add Theme Picker Page
import 'package:app_theme_picker/app_theme_picker.dart';
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('My App')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PickThemePage(
size: 60.0, // Button size
),
),
);
},
child: Text('Choose Theme'),
),
),
);
}
}
3. Using Theme Picker Tile
For a more compact interface, use the ThemePickTile:
import 'package:app_theme_picker/app_theme_picker.dart';
ListTile(
title: Text('Theme'),
subtitle: ThemePickTile(
size: 40.0,
availableSchemes: {'sakura', 'material', 'blue'}, // Optional: limit schemes
),
)
Advanced Usage
Custom Available Schemes
You can limit which color schemes are available:
PickThemePage(
size: 60.0,
availableSchemes: {
'material',
'materialHc',
'blue',
'indigo',
'sakura',
'mandyRed',
},
)
Individual Theme Components
Use individual components for custom layouts:
// Theme mode buttons
Row(
children: [
ThemeModeButton(mode: ThemeMode.light),
ThemeModeButton(mode: ThemeMode.system),
ThemeModeButton(mode: ThemeMode.dark),
],
)
// Individual color button
ThemeColorButton(
schemeData: FlexColor.schemes[FlexScheme.sakura]!,
onTap: () {
ref.read(themePodProvider.notifier).changeTheme(FlexScheme.sakura);
},
size: 50.0,
selected: currentScheme == FlexScheme.sakura,
)
Accessing Theme State
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// Watch current theme
final currentTheme = ref.watch(themePodProvider);
final currentThemeMode = ref.watch(themeModePodProvider);
// Programmatically change theme
void changeToSakura() {
ref.read(themePodProvider.notifier).changeTheme(FlexScheme.sakura);
}
void changeToDarkMode() {
ref.read(themeModePodProvider.notifier).changeThemeMode(ThemeMode.dark);
}
return YourWidget();
}
}
Localization
The package supports multiple languages out of the box:
- English (en-US)
- Japanese (ja-JP)
- Korean (ko)
- Chinese (zh-CN)
To enable localization in your app, set up easy_localization:
import 'package:easy_localization/easy_localization.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
supportedLocales: [
Locale('en', 'US'),
Locale('ja', 'JP'),
Locale('ko'),
Locale('zh', 'CN'),
],
path: 'assets/localizations',
fallbackLocale: Locale('en', 'US'),
child: ProviderScope(child: MyApp()),
),
);
}
Testing with Mocks
The package provides mock implementations for testing purposes. These are useful when you need to override theme providers in your tests.
Available Theme Mocks
All 69 FlexScheme themes have corresponding mock classes:
import 'package:app_theme_picker/app_theme_picker.dart';
// Material Design themes
MaterialThemeMock()
MaterialHcThemeMock()
BlueThemeMock()
IndigoThemeMock()
// Color-based themes
SakuraThemeMock()
MandyRedThemeMock()
RedThemeMock()
RedWineThemeMock()
// ... and 60+ more theme mocks
// Custom theme
CustomThemeMock()
Available Theme Mode Mocks
import 'package:app_theme_picker/app_theme_picker.dart';
// Theme mode mocks
LightThemeModeMock() // Returns ThemeMode.light
DarkThemeModeMock() // Returns ThemeMode.dark
Using Mocks in Tests
You can override providers with mocks in your widget tests:
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:app_theme_picker/app_theme_picker.dart';
void main() {
testWidgets('Test with sakura theme', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
// Override theme provider with mock
themePodProvider.overrideWith((ref) => SakuraThemeMock()),
// Override theme mode provider with mock
themeModePodProvider.overrideWith((ref) => DarkThemeModeMock()),
],
child: MyApp(),
),
);
// Your test code here
});
}
Example: Testing Different Theme Combinations
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:app_theme_picker/app_theme_picker.dart';
void main() {
group('Theme Tests', () {
testWidgets('Test with Material theme in light mode', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
themePodProvider.overrideWith((ref) => MaterialThemeMock()),
themeModePodProvider.overrideWith((ref) => LightThemeModeMock()),
],
child: MyApp(),
),
);
// Verify light theme is applied
// Your assertions here
});
testWidgets('Test with Sakura theme in dark mode', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
themePodProvider.overrideWith((ref) => SakuraThemeMock()),
themeModePodProvider.overrideWith((ref) => DarkThemeModeMock()),
],
child: MyApp(),
),
);
// Verify dark theme is applied
// Your assertions here
});
});
}
Using Pre-defined Overrides
For convenience, the package provides pre-defined override variables that make testing even easier:
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:app_theme_picker/app_theme_picker.dart';
void main() {
testWidgets('Test with pre-defined overrides', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
// Use pre-defined override variables
sakuraThemeOverride,
darkThemeOverride,
],
child: MyApp(),
),
);
// Your test code here
});
}
Available Pre-defined Overrides
Theme Mode Overrides:
lightThemeOverride // Sets theme mode to light
darkThemeOverride // Sets theme mode to dark
Theme Overrides:
All 69 FlexScheme themes have corresponding override variables following the pattern {schemeName}ThemeOverride:
// Material Design
materialThemeOverride
materialHcThemeOverride
materialBaselineThemeOverride
// Blue variants
blueThemeOverride
indigoThemeOverride
hippieBlueThemeOverride
aquaBlueThemeOverride
brandBlueThemeOverride
deepBlueThemeOverride
// ... and more
// Popular themes
sakuraThemeOverride
mandyRedThemeOverride
redThemeOverride
greenThemeOverride
goldThemeOverride
// Material 3 colors
redM3ThemeOverride
pinkM3ThemeOverride
blueM3ThemeOverride
// ... all M3 colors
// Shadcn inspired
shadBlueThemeOverride
shadGrayThemeOverride
shadGreenThemeOverride
// ... all shad variants
customThemeOverride
Complete List of Theme Mocks
Click to expand all 69 theme mocks
Material Design Themes:
MaterialThemeMock- Material Design guide exampleMaterialHcThemeMock- Material high contrastMaterialBaselineThemeMock- Material 3 baseline
Blue Themes:
BlueThemeMock,IndigoThemeMock,HippieBlueThemeMock,AquaBlueThemeMockBrandBlueThemeMock,DeepBlueThemeMock,BahamaBlueThemeMock,SanJuanBlueThemeMockBlumineBlueThemeMock,BlueWhaleThemeMock,EbonyClayThemeMock,BigStoneThemeMock
Red/Pink Themes:
SakuraThemeMock,MandyRedThemeMock,RedThemeMock,RedWineThemeMockBarossaThemeMock,DamaskThemeMock,RosewoodThemeMock
Purple/Brown Themes:
PurpleBrownThemeMock,DeepPurpleThemeMock
Green Themes:
GreenThemeMock,MoneyThemeMock,JungleThemeMock,MallardGreenThemeMockVerdunHemlockThemeMock,DellGenoaThemeMock
Yellow/Gold/Orange Themes:
GoldThemeMock,MangoThemeMock,AmberThemeMock,VesuviusBurnThemeMock
Grey/Neutral Themes:
GreyLawThemeMock,WasabiThemeMock,SharkThemeMock,EspressoThemeMockOuterSpaceThemeMock
Special Themes:
FlutterDashThemeMock- Based on Flutter Dash mascot
Material 3 Color Themes:
RedM3ThemeMock,PinkM3ThemeMock,PurpleM3ThemeMock,IndigoM3ThemeMockBlueM3ThemeMock,CyanM3ThemeMock,TealM3ThemeMock,GreenM3ThemeMockLimeM3ThemeMock,YellowM3ThemeMock,OrangeM3ThemeMock,DeepOrangeM3ThemeMock
Monochrome Themes:
BlackWhiteThemeMock,GreysThemeMock,SepiaThemeMock
Shadcn Inspired Themes:
ShadBlueThemeMock,ShadGrayThemeMock,ShadGreenThemeMock,ShadNeutralThemeMockShadOrangeThemeMock,ShadRedThemeMock,ShadRoseThemeMock,ShadSlateThemeMockShadStoneThemeMock,ShadVioletThemeMock,ShadYellowThemeMock,ShadZincThemeMock
Custom:
CustomThemeMock- Placeholder for custom themes
API Reference
PickThemePage
Main theme selection page widget.
| Parameter | Type | Description | Default |
|---|---|---|---|
size |
double |
Size of theme color buttons | Required |
availableSchemes |
Set<String>? |
Limit available color schemes | null (all schemes) |
ThemePickTile
Compact theme selection tile widget.
| Parameter | Type | Description | Default |
|---|---|---|---|
size |
double |
Size of theme color buttons | 40.0 |
availableSchemes |
Set<String>? |
Limit available color schemes | null (all schemes) |
ThemeColorButton
Individual color scheme button.
| Parameter | Type | Description | Default |
|---|---|---|---|
schemeData |
FlexSchemeData |
Color scheme data | Required |
onTap |
VoidCallback |
Tap callback | Required |
selected |
bool |
Whether button is selected | Required |
size |
double |
Button size | 50.0 |
ThemeModeButton
Individual theme mode button (Light/Dark/System).
| Parameter | Type | Description | Default |
|---|---|---|---|
mode |
ThemeMode |
Theme mode | Required |
State Providers
themePodProvider: Current color scheme (AsyncValue<FlexScheme>)themeModePodProvider: Current theme mode (AsyncValue<ThemeMode>)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Author
Normidar
Support
If you find this package helpful, please consider:
- ⭐ Starring the repository
- 🐛 Reporting bugs
- 💡 Suggesting new features
- ☕ Sponsoring the developer
Changelog
See CHANGELOG.md for a detailed list of changes.