added dynamic colors

This commit is contained in:
Vadim 2023-01-21 22:29:02 +03:00
parent 9be413752a
commit d30295048b
5 changed files with 66 additions and 40 deletions

View file

@ -30,20 +30,21 @@ class Application extends StatelessWidget {
return MultiProvider( return MultiProvider(
providers: [ providers: [
Provider(create: (_) => UserPreferencesService(snapshot.data!)), Provider(create: (_) => UserPreferencesService(snapshot.data!)),
Provider(create: (_) => HapticsService()), Provider(create: (_) => const HapticsService()),
Provider(create: (_) => PermissionsService()),
Provider.value(value: evSource), Provider.value(value: evSource),
], ],
child: Provider(
create: (_) => PermissionsService(),
child: StopTypeProvider( child: StopTypeProvider(
child: ThemeProvider( child: ThemeProvider(
initialPrimaryColor: const Color(0xFF2196f3), builder: (context, _) {
builder: (context, child) => AnnotatedRegion( final systemIconsBrightness =
ThemeData.estimateBrightnessForColor(context.watch<ThemeData>().colorScheme.onSurface);
return AnnotatedRegion(
value: SystemUiOverlayStyle( value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent, statusBarColor: Colors.transparent,
statusBarIconBrightness: statusBarIconBrightness: systemIconsBrightness,
ThemeData.estimateBrightnessForColor(context.watch<ThemeData>().colorScheme.onSurface),
systemNavigationBarColor: context.watch<ThemeData>().colorScheme.surface, systemNavigationBarColor: context.watch<ThemeData>().colorScheme.surface,
systemNavigationBarIconBrightness: systemIconsBrightness,
), ),
child: MaterialApp( child: MaterialApp(
theme: context.watch<ThemeData>(), theme: context.watch<ThemeData>(),
@ -64,8 +65,8 @@ class Application extends StatelessWidget {
"settings": (context) => const SettingsScreen(), "settings": (context) => const SettingsScreen(),
}, },
), ),
), );
), },
), ),
), ),
); );

View file

@ -1,6 +1,8 @@
import 'package:vibration/vibration.dart'; import 'package:vibration/vibration.dart';
class HapticsService { class HapticsService {
const HapticsService();
Future<void> quickVibration() async => _tryVibrate(duration: 25, amplitude: 96); Future<void> quickVibration() async => _tryVibrate(duration: 25, amplitude: 96);
Future<void> responseVibration() async => _tryVibrate(duration: 50, amplitude: 128); Future<void> responseVibration() async => _tryVibrate(duration: 50, amplitude: 128);

View file

@ -1,3 +1,4 @@
import 'package:dynamic_color/dynamic_color.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:lightmeter/data/models/theme_type.dart'; import 'package:lightmeter/data/models/theme_type.dart';
@ -7,12 +8,10 @@ import 'package:material_color_utilities/material_color_utilities.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class ThemeProvider extends StatefulWidget { class ThemeProvider extends StatefulWidget {
final Color initialPrimaryColor;
final Widget? child; final Widget? child;
final TransitionBuilder? builder; final TransitionBuilder? builder;
const ThemeProvider({ const ThemeProvider({
required this.initialPrimaryColor,
this.child, this.child,
this.builder, this.builder,
super.key, super.key,
@ -28,7 +27,10 @@ class ThemeProvider extends StatefulWidget {
class ThemeProviderState extends State<ThemeProvider> { class ThemeProviderState extends State<ThemeProvider> {
late ThemeType _themeType; late ThemeType _themeType;
late Color _primaryColor = widget.initialPrimaryColor; Color _primaryColor = const Color(0xFF2196f3);
bool _allowDynamicColors = false;
bool get allowDynamicColors => _allowDynamicColors;
@override @override
void initState() { void initState() {
@ -38,17 +40,30 @@ class ThemeProviderState extends State<ThemeProvider> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) {
_allowDynamicColors = lightDynamic != null && darkDynamic != null;
if (_allowDynamicColors) {
final dynamicColorScheme = _themeBrightness == Brightness.light ? lightDynamic : darkDynamic;
if (dynamicColorScheme != null) {
_primaryColor = dynamicColorScheme.primary;
}
}
return Provider.value( return Provider.value(
value: _themeType, value: _themeType,
child: Provider.value( child: Provider.value(
value: _themeFromColor( value: _themeFromColorScheme(
_colorSchemeFromColor(
_primaryColor, _primaryColor,
_mapThemeTypeToBrightness(_themeType), _themeBrightness,
),
), ),
builder: widget.builder, builder: widget.builder,
child: widget.child, child: widget.child,
), ),
); );
},
);
} }
void setThemeType(ThemeType themeType) { void setThemeType(ThemeType themeType) {
@ -62,6 +77,17 @@ class ThemeProviderState extends State<ThemeProvider> {
context.read<UserPreferencesService>().themeType = themeType; context.read<UserPreferencesService>().themeType = themeType;
} }
Brightness get _themeBrightness {
switch (_themeType) {
case ThemeType.light:
return Brightness.light;
case ThemeType.dark:
return Brightness.dark;
case ThemeType.systemDefault:
return SchedulerBinding.instance.platformDispatcher.platformBrightness;
}
}
void setPrimaryColor(Color color) { void setPrimaryColor(Color color) {
if (color == _primaryColor) { if (color == _primaryColor) {
return; return;
@ -72,20 +98,9 @@ class ThemeProviderState extends State<ThemeProvider> {
}); });
} }
Brightness _mapThemeTypeToBrightness(ThemeType themeType) { ColorScheme _colorSchemeFromColor(Color color, Brightness brightness) {
switch (themeType) {
case ThemeType.light:
return Brightness.light;
case ThemeType.dark:
return Brightness.dark;
case ThemeType.systemDefault:
return SchedulerBinding.instance.platformDispatcher.platformBrightness;
}
}
ThemeData _themeFromColor(Color color, Brightness brightness) {
final scheme = brightness == Brightness.light ? Scheme.light(color.value) : Scheme.dark(color.value); final scheme = brightness == Brightness.light ? Scheme.light(color.value) : Scheme.dark(color.value);
final colorScheme = ColorScheme( return ColorScheme(
brightness: brightness, brightness: brightness,
primary: Color(scheme.primary), primary: Color(scheme.primary),
onPrimary: Color(scheme.onPrimary), onPrimary: Color(scheme.onPrimary),
@ -102,9 +117,18 @@ class ThemeProviderState extends State<ThemeProvider> {
surfaceVariant: Color.alphaBlend(Color(scheme.primary).withOpacity(0.5), Color(scheme.background)), surfaceVariant: Color.alphaBlend(Color(scheme.primary).withOpacity(0.5), Color(scheme.background)),
onSurfaceVariant: Color(scheme.onSurfaceVariant), onSurfaceVariant: Color(scheme.onSurfaceVariant),
); );
}
ThemeData _themeFromColorScheme(ColorScheme scheme) {
return ThemeData( return ThemeData(
useMaterial3: true, useMaterial3: true,
colorScheme: colorScheme, bottomAppBarColor: scheme.surface,
brightness: scheme.brightness,
colorScheme: scheme,
dialogBackgroundColor: scheme.surface,
dialogTheme: DialogTheme(backgroundColor: scheme.surface),
scaffoldBackgroundColor: scheme.surface,
toggleableActiveColor: scheme.primary,
); );
} }
} }

View file

@ -13,7 +13,6 @@ class SettingsScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
backgroundColor: Theme.of(context).colorScheme.surface,
body: SafeArea( body: SafeArea(
top: false, top: false,
child: CustomScrollView( child: CustomScrollView(

View file

@ -9,6 +9,7 @@ environment:
dependencies: dependencies:
camera: 0.10.0+4 camera: 0.10.0+4
exif: 3.1.2 exif: 3.1.2
dynamic_color: 1.5.4
flutter: flutter:
sdk: flutter sdk: flutter
flutter_bloc: 8.1.1 flutter_bloc: 8.1.1
@ -28,7 +29,6 @@ dev_dependencies:
flutter_launcher_icons: 0.11.0 flutter_launcher_icons: 0.11.0
flutter_lints: 2.0.0 flutter_lints: 2.0.0
flutter_native_splash: 2.2.16 flutter_native_splash: 2.2.16
test: 1.21.6
dependency_overrides: dependency_overrides:
material_color_utilities: 0.2.0 material_color_utilities: 0.2.0