Skip to content

Instantly share code, notes, and snippets.

@Roaa94
Last active November 17, 2022 10:38
Show Gist options
  • Save Roaa94/e270f22c0270a16748ae3193d87b4d82 to your computer and use it in GitHub Desktop.
Save Roaa94/e270f22c0270a16748ae3193d87b4d82 to your computer and use it in GitHub Desktop.
Theme and Primary Color Switcher Full Code
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(App());
}
const double _containerWidth = 450.0;
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Rebuilt App!');
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (_) => ThemeProvider(),
),
],
child: Consumer<ThemeProvider>(
child: HomePage(),
builder: (c, themeProvider, child) {
return MaterialApp(
debugShowCheckedModeBanner: false,
themeMode: themeProvider.selectedThemeMode,
theme: ThemeData(
brightness: Brightness.light,
primarySwatch: AppColors.getMaterialColorFromColor(themeProvider.selectedPrimaryColor),
primaryColor: themeProvider.selectedPrimaryColor,
),
darkTheme: ThemeData(
brightness: Brightness.dark,
primarySwatch: AppColors.getMaterialColorFromColor(themeProvider.selectedPrimaryColor),
primaryColor: themeProvider.selectedPrimaryColor,
),
home: child,
);
},
),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Theme & Primary Color Switcher'),
),
body: Center(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 17),
width: _containerWidth,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: Text('Theme'),
),
ThemeSwitcher(),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10),
child: Text('Primary Color'),
),
PrimaryColorSwitcher(),
],
),
),
),
);
}
}
class ThemeProvider with ChangeNotifier {
ThemeMode selectedThemeMode = appThemes[0].mode;
setSelectedThemeMode(ThemeMode _themeMode) {
selectedThemeMode = _themeMode;
notifyListeners();
}
Color selectedPrimaryColor = AppColors.primaryColors[0];
setSelectedPrimaryColor(Color _color) {
selectedPrimaryColor = _color;
notifyListeners();
}
}
class ThemeSwitcher extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(
builder: (c, themeProvider, _) => SizedBox(
height: (_containerWidth - (17 * 2) - (10 * 2)) / 3,
child: GridView.count(
physics: const NeverScrollableScrollPhysics(),
crossAxisSpacing: 10,
crossAxisCount: appThemes.length,
children: List.generate(
appThemes.length,
(i) {
bool _isSelectedTheme = appThemes[i].mode == themeProvider.selectedThemeMode;
return GestureDetector(
onTap: _isSelectedTheme ? null : () => themeProvider.setSelectedThemeMode(appThemes[i].mode),
child: AnimatedContainer(
height: 100,
duration: const Duration(milliseconds: 200),
decoration: BoxDecoration(
color: _isSelectedTheme ? Theme.of(context).primaryColor : Colors.transparent,
borderRadius: BorderRadius.circular(10),
border: Border.all(width: 2, color: Theme.of(context).primaryColor),
),
child: Center(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 7),
margin: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context).cardColor.withOpacity(0.5),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(appThemes[i].icon),
Text(
appThemes[i].title,
style: Theme.of(context).textTheme.subtitle2,
),
],
),
),
),
),
);
},
),
),
),
);
}
}
class PrimaryColorSwitcher extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<ThemeProvider>(
builder: (c, themeProvider, _) => SizedBox(
height: (_containerWidth - (17 * 2) - (10 * 2)) / 3,
child: GridView.count(
crossAxisCount: AppColors.primaryColors.length,
physics: const NeverScrollableScrollPhysics(),
crossAxisSpacing: 10,
children: List.generate(
AppColors.primaryColors.length,
(i) {
bool _isSelectedColor = AppColors.primaryColors[i] == themeProvider.selectedPrimaryColor;
return GestureDetector(
onTap: _isSelectedColor ? null : () => themeProvider.setSelectedPrimaryColor(AppColors.primaryColors[i]),
child: Container(
height: 50,
decoration: BoxDecoration(
color: AppColors.primaryColors[i],
borderRadius: BorderRadius.circular(10),
),
child: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: _isSelectedColor ? 1 : 0,
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: Theme.of(context).cardColor.withOpacity(0.5),
),
child: const Icon(
Icons.check,
size: 20,
),
),
),
),
),
),
);
},
),
),
),
);
}
}
class AppColors {
static List<Color> primaryColors = const [
Color(0xffd23156),
Color(0xff16b9fd),
Color(0xff13d0c1),
Color(0xffe5672f),
Color(0xffb73d99),
];
static Color getShade(Color color, {bool darker = false, double value = .1}) {
assert(value >= 0 && value <= 1);
final hsl = HSLColor.fromColor(color);
final hslDark = hsl.withLightness((darker ? (hsl.lightness - value) : (hsl.lightness + value)).clamp(0.0, 1.0));
return hslDark.toColor();
}
static MaterialColor getMaterialColorFromColor(Color color) {
Map<int, Color> _colorShades = {
50: getShade(color, value: 0.5),
100: getShade(color, value: 0.4),
200: getShade(color, value: 0.3),
300: getShade(color, value: 0.2),
400: getShade(color, value: 0.1),
500: color,
600: getShade(color, value: 0.1, darker: true),
700: getShade(color, value: 0.15, darker: true),
800: getShade(color, value: 0.2, darker: true),
900: getShade(color, value: 0.25, darker: true),
};
return MaterialColor(color.value, _colorShades);
}
}
class AppTheme {
ThemeMode mode;
String title;
IconData icon;
AppTheme({
required this.mode,
required this.title,
required this.icon,
});
}
List<AppTheme> appThemes = [
AppTheme(
mode: ThemeMode.light,
title: 'Light',
icon: Icons.brightness_5_rounded,
),
AppTheme(
mode: ThemeMode.dark,
title: 'Dark',
icon: Icons.brightness_2_rounded,
),
AppTheme(
mode: ThemeMode.system,
title: 'Auto',
icon: Icons.brightness_4_rounded,
),
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment