Skip to content

Commit

Permalink
Custom surfaceTint and surface blends support in Playground
Browse files Browse the repository at this point in the history
  • Loading branch information
rydmike committed Jul 6, 2022
1 parent 2000d65 commit 2249169
Show file tree
Hide file tree
Showing 11 changed files with 222 additions and 9 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Expand Up @@ -118,8 +118,8 @@ All notable changes to the **FlexColorScheme** package are documented here.
the same issue the Playground app did, but the issue is a Flutter SDK issue that FlexColorScheme
cannot fix. Most likely 99% of apps will never run into this issue.

* **TODO**: Add support in Themes Playground to customize `surfaceTint` color and hence also the
used color for surface blends.
* Added support in Themes Playground to customize `surfaceTint` color, and also use it as custom
color for surface blends.

## v5.0.1 - April 29, 2022

Expand Down
2 changes: 2 additions & 0 deletions example/lib/example5/theme/flex_theme_dark.dart
Expand Up @@ -208,6 +208,8 @@ FlexColorScheme flexColorSchemeDark(ThemeController controller) {
useMaterial3ErrorColors: controller.useM3ErrorColors,
tones:
AppColor.flexTonesConfig(Brightness.dark, controller.usedFlexToneSetup),
// Use custom surface tint color.
surfaceTint: controller.surfaceTintDark,
//
// ThemeData properties passed along directly to ThemeData.
visualDensity: AppData.visualDensity,
Expand Down
2 changes: 2 additions & 0 deletions example/lib/example5/theme/flex_theme_light.dart
Expand Up @@ -270,6 +270,8 @@ FlexColorScheme flexColorSchemeLight(ThemeController controller) {
// between a few pre-configured ones.
tones: AppColor.flexTonesConfig(
Brightness.light, controller.usedFlexToneSetup),
// Use custom surface tint color.
surfaceTint: controller.surfaceTintLight,
//
// ThemeData properties passed along directly to ThemeData.
//
Expand Down
8 changes: 8 additions & 0 deletions example/lib/example5/utils/generate_theme_dart_code.dart
Expand Up @@ -143,6 +143,12 @@ String generateThemeDartCode(ThemeController controller) {
final String useMaterial3 = controller.useMaterial3
? ' useMaterial3: ${controller.useMaterial3},\n'
: '';
final String tintLightColor = controller.surfaceTintLight != null
? ' surfaceTint: ${controller.surfaceTintLight},\n'
: '';
final String tintDarkColor = controller.surfaceTintDark != null
? ' surfaceTint: ${controller.surfaceTintDark},\n'
: '';
//
// Code for FlexSubThemesData setup.
//
Expand Down Expand Up @@ -855,6 +861,7 @@ String generateThemeDartCode(ThemeController controller) {
'$tabBarStyle'
'$lightIsWhite'
'$swapLightColors'
'$tintLightColor'
'$tooltipsMatchBackground'
'$lightSubTheme'
'$useKeyColorsLight'
Expand All @@ -877,6 +884,7 @@ String generateThemeDartCode(ThemeController controller) {
'$tabBarStyle'
'$darkIsTrueBlack'
'$swapDarkColors'
'$tintDarkColor'
'$tooltipsMatchBackground'
'$darkSubTheme'
'$useKeyColorsDark'
Expand Down
Expand Up @@ -1049,6 +1049,29 @@ class SchemeColors extends StatelessWidget {
),
),
),
const Divider(height: 1, thickness: 1),
Expanded(
child: MouseRegion(
onEnter: (PointerEvent details) {
tc.setHoverColor(colorScheme.surfaceTint);
tc.setHoverTonalPalette(TonalPalettes.primary);
},
onExit: (PointerEvent details) {
tc.setHoverColor(null);
tc.setHoverTonalPalette(null);
},
child: Material(
color: colorScheme.surfaceTint,
child: ColorNameValue(
color: colorScheme.surfaceTint,
textColor: _onColor(colorScheme.surfaceTint),
label: 'surfaceTint',
tone: tones.primaryTone,
showTone: showTones,
),
),
),
),
],
),
),
Expand Down
@@ -1,8 +1,11 @@
import 'package:flex_color_picker/flex_color_picker.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';

import '../../../../shared/controllers/theme_controller.dart';
import '../../../../shared/widgets/universal/switch_list_tile_adaptive.dart';
import '../../shared/color_picker_inkwell.dart';
import '../../shared/color_scheme_popup_menu.dart';
import 'surface_mode_buttons.dart';

// Panel used to define how primary color is blended into surfaces and
Expand Down Expand Up @@ -53,7 +56,36 @@ class SurfaceBlends extends StatelessWidget {

@override
Widget build(BuildContext context) {
final bool isLight = Theme.of(context).brightness == Brightness.light;
final ThemeData theme = Theme.of(context);
final bool isLight = theme.brightness == Brightness.light;
final ColorScheme colorScheme = theme.colorScheme;

// Default color is in use, make a light label to use in custom color.
final String defaultTintLightLabel =
controller.surfaceTintLight == null ? ' primary (default):' : ':';
// Current light tint color
final Color? previousTintLight = controller.surfaceTintLight;
final Color effectiveTintLight =
controller.surfaceTintLight ?? colorScheme.surfaceTint;
// Names for the light tint colors.
final String materialNameLight =
ColorTools.materialName(effectiveTintLight);
final String nameThatColorLight =
ColorTools.nameThatColor(effectiveTintLight);
final String spaceLight = materialNameLight == '' ? '' : ' ';
// Default color is in use, make a dark label to use in custom color.
final String defaultTintDarkLabel =
controller.surfaceTintDark == null ? ' primary (default)' : '';
// Current dark tint color.
final Color? previousTintDark = controller.surfaceTintDark;
final Color effectiveTintDark =
controller.surfaceTintDark ?? colorScheme.surfaceTint;
// Names for the dark tint colors.
final String materialNameDark = ColorTools.materialName(effectiveTintDark);
final String nameThatColorDark =
ColorTools.nameThatColor(effectiveTintDark);
final String spaceDark = materialNameDark == '' ? '' : ' ';
//
return Column(
children: <Widget>[
const SizedBox(height: 8),
Expand Down Expand Up @@ -89,6 +121,45 @@ class SurfaceBlends extends StatelessWidget {
const SizedBox(width: 16),
],
),
const SizedBox(height: 8),
ListTile(
enabled: controller.surfaceTintLight != null,
title: const Text('Set light blend and tint color back to default'),
subtitle: const Text('Sets custom blend and tint color back '
'to primary color'),
trailing: ElevatedButton(
onPressed: controller.surfaceTintLight != null
? () {
controller.setSurfaceTintLight(null);
}
: null,
child: const Text('Default'),
),
onTap: () {
controller.setSurfaceTintLight(null);
},
),
ColorPickerInkWell(
color: controller.surfaceTintLight ?? colorScheme.primary,
onChanged: controller.setSurfaceTintLight,
recentColors: controller.recentColors,
onRecentColorsChanged: controller.setRecentColors,
wasCancelled: (bool cancelled) {
if (cancelled) {
controller.setSurfaceTintLight(previousTintLight);
}
},
enabled: true,
child: ListTile(
title: const Text('Light theme blend and surface tint color'),
subtitle: Text('Color$defaultTintLightLabel '
'$nameThatColorLight $materialNameLight$spaceLight'
'#${effectiveTintLight.hexCode}'),
trailing: ColorSchemeBox(
color: controller.surfaceTintLight ?? colorScheme.primary,
),
),
),
const ListTile(
title: Text('Light theme blend level'),
subtitle: Text('Adjust the surface, background, scaffold and '
Expand Down Expand Up @@ -213,6 +284,45 @@ class SurfaceBlends extends StatelessWidget {
const SizedBox(width: 16),
],
),
const SizedBox(height: 8),
ListTile(
enabled: controller.surfaceTintDark != null,
title: const Text('Set dark blend and tint color back to default'),
subtitle: const Text('Sets custom blend and tint color back '
'to primary color'),
trailing: ElevatedButton(
onPressed: controller.surfaceTintDark != null
? () {
controller.setSurfaceTintDark(null);
}
: null,
child: const Text('Default'),
),
onTap: () {
controller.setSurfaceTintDark(null);
},
),
ColorPickerInkWell(
color: controller.surfaceTintDark ?? colorScheme.primary,
onChanged: controller.setSurfaceTintDark,
recentColors: controller.recentColors,
onRecentColorsChanged: controller.setRecentColors,
wasCancelled: (bool cancelled) {
if (cancelled) {
controller.setSurfaceTintDark(previousTintDark);
}
},
enabled: true,
child: ListTile(
title: const Text('Dark theme blend and surface tint color'),
subtitle: Text('Color$defaultTintDarkLabel '
'$nameThatColorDark $materialNameDark$spaceDark'
'#${effectiveTintDark.hexCode}'),
trailing: ColorSchemeBox(
color: controller.surfaceTintDark ?? colorScheme.primary,
),
),
),
const ListTile(
title: Text('Dark theme blend level'),
subtitle: Text('Adjust the surface, background, scaffold and '
Expand Down
11 changes: 6 additions & 5 deletions example/lib/example5/widgets/shared/color_picker_inkwell.dart
Expand Up @@ -225,12 +225,13 @@ class ColorPickerInkWell extends StatelessWidget {
final bool isLight = Theme.of(context).brightness == Brightness.light;

return InkWell(
// TODO(rydmike): Remove this commented customized InkWell style.
// We want a bit more pronounced hover color for this case than normally.
hoverColor: isLight ? const Color(0x40BCBCBC) : const Color(0x30FFFFFF),
splashColor: isLight ? const Color(0x40BCBCBC) : const Color(0x30FFFFFF),
focusColor: isLight ? const Color(0x40BCBCBC) : const Color(0x30FFFFFF),
highlightColor:
isLight ? const Color(0x40BCBCBC) : const Color(0x30FFFFFF),
// hoverColor: isLight ? const Color(0x40BCBCBC):const Color(0x30FFFFFF),
// splashColor: isLight ? const Color(0x40BCBCBC):const Color(0x30FFFFFF),
// focusColor: isLight ? const Color(0x40BCBCBC):const Color(0x30FFFFFF),
// highlightColor:
// isLight ? const Color(0x40BCBCBC) : const Color(0x30FFFFFF),
onHover: (bool value) {
onHover?.call(value);
},
Expand Down
Expand Up @@ -16,13 +16,15 @@ class ColorSchemePopupMenu extends StatelessWidget {
this.subtitle,
this.contentPadding,
this.labelForDefault = 'default (primary)',
this.popupLabelDefault,
});
final int index;
final ValueChanged<int>? onChanged;
final Widget? title;
final Widget? subtitle;
final EdgeInsetsGeometry? contentPadding; // Defaults to 16.
final String labelForDefault;
final String? popupLabelDefault;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -68,7 +70,7 @@ class ColorSchemePopupMenu extends StatelessWidget {
),
title: i >= SchemeColor.values.length - 2
// If we reached first deprecated color, make default label.
? Text(labelForDefault, style: txtStyle)
? Text(popupLabelDefault ?? labelForDefault, style: txtStyle)
: Text(SchemeColor.values[i].name, style: txtStyle),
),
)
Expand Down
29 changes: 29 additions & 0 deletions example/lib/shared/const/store.dart
Expand Up @@ -788,6 +788,35 @@ class Store {
// We use NULL as default, on nullable settings.
static const double? defaultDialogBorderRadius = null;

// Custom surface tint color SETTINGS.
// ===========================================================================

// Key used to read and save the surfaceTintLight color value.
static const String keySurfaceTintLight = 'surfaceTintLight';
// Default value for the surfaceTintLight color, also to reset settings.
// We use NULL as default, on nullable settings.
static const Color? defaultSurfaceTintLight = null;

// Key used to read and save the surfaceTintLightSchemeColor value.
static const String keySurfaceTintLightSchemeColor =
'surfaceTintLightSchemeColor';
// Default value for the surfaceTintLightSchemeColor, also used to
// reset settings. We use NULL as default, on nullable settings.
static const SchemeColor? defaultSurfaceTintLightSchemeColor = null;

// Key used to read and save the surfaceTintDark color value.
static const String keySurfaceTintDark = 'surfaceTintDark';
// Default value for the surfaceTintDark color, also to reset settings.
// We use NULL as default, on nullable settings.
static const Color? defaultSurfaceTintDark = null;

// Key used to read and save the surfaceTintDarkSchemeColor value.
static const String keySurfaceTintDarkSchemeColor =
'surfaceTintDarkSchemeColor';
// Default value for the surfaceTintDarkSchemeColor, also used to
// reset settings. We use NULL as default, on nullable settings.
static const SchemeColor? defaultSurfaceTintDarkSchemeColor = null;

// Custom color SETTINGS.
// ===========================================================================

Expand Down
32 changes: 32 additions & 0 deletions example/lib/shared/controllers/theme_controller.dart
Expand Up @@ -373,6 +373,12 @@ class ThemeController with ChangeNotifier {
_dialogBorderRadius = await _themeService.load(
Store.keyDialogBorderRadius, Store.defaultDialogBorderRadius);
//
// Custom surface tint color SETTINGS.
_surfaceTintLight = await _themeService.load(
Store.keySurfaceTintLight, Store.defaultSurfaceTintLight);
_surfaceTintDark = await _themeService.load(
Store.keySurfaceTintDark, Store.defaultSurfaceTintDark);
//
// Custom color SETTINGS.
_primaryLight = await _themeService.load(
Store.keyPrimaryLight, Store.defaultPrimaryLight);
Expand Down Expand Up @@ -617,6 +623,11 @@ class ThemeController with ChangeNotifier {
await setDialogBackgroundSchemeColor(
Store.defaultDialogBackgroundSchemeColor, false);
await setDialogBorderRadius(Store.defaultDialogBorderRadius, false);
//
// Surface tint colors.
await setSurfaceTintLight(Store.defaultSurfaceTintLight, false);
await setSurfaceTintDark(Store.defaultSurfaceTintDark, false);
//
// Not persisted, locally controlled popup selection for ThemeService,
// resets to actual used platform when settings are reset or app loaded.
await setPlatform(defaultTargetPlatform, false);
Expand Down Expand Up @@ -2001,6 +2012,27 @@ class ThemeController with ChangeNotifier {
await _themeService.save(Store.keyDialogBorderRadius, value);
}

// Custom surface tint color SETTINGS.
// ===========================================================================

late Color? _surfaceTintLight;
Color? get surfaceTintLight => _surfaceTintLight;
Future<void> setSurfaceTintLight(Color? value, [bool notify = true]) async {
if (value == _surfaceTintLight) return;
_surfaceTintLight = value;
if (notify) notifyListeners();
await _themeService.save(Store.keySurfaceTintLight, value);
}

late Color? _surfaceTintDark;
Color? get surfaceTintDark => _surfaceTintDark;
Future<void> setSurfaceTintDark(Color? value, [bool notify = true]) async {
if (value == _surfaceTintDark) return;
_surfaceTintDark = value;
if (notify) notifyListeners();
await _themeService.save(Store.keySurfaceTintDark, value);
}

// Custom color SETTINGS.
// ===========================================================================

Expand Down
4 changes: 4 additions & 0 deletions lib/src/flex_color_scheme.dart
Expand Up @@ -2603,6 +2603,7 @@ class FlexColorScheme with Diagnosticable {
tertiaryKey: seed.useTertiary ? effectiveColors.tertiary : null,
// Use provided tones configuration or default one.
tones: tones ?? const FlexTones.light(),
surfaceTint: surfaceTint,
);
// Update effective main colors to seed colors, keeping configured
// effective main color values when so defined.
Expand Down Expand Up @@ -2795,6 +2796,7 @@ class FlexColorScheme with Diagnosticable {
// surfaceVariant and inverseSurface on purpose.
surfaceVariant: effectiveSurfaceVariantColor,
inverseSurface: effectiveInverseSurfaceColor,
surfaceTint: surfaceTint,
) ??
// We had a colorScheme passed in, we use as passed in, but set
// override values for props we have not handled via FCS direct
Expand Down Expand Up @@ -4294,6 +4296,7 @@ class FlexColorScheme with Diagnosticable {
// defaults that can produce same results as Flutter SDK,
// ColorScheme.fromSeed(color), when only primary color is used as key.
tones: tones ?? const FlexTones.dark(),
surfaceTint: surfaceTint,
);
// Update effective main colors to seed colors, keeping configured
// effective main color values when so defined. The main colors to keep
Expand Down Expand Up @@ -4487,6 +4490,7 @@ class FlexColorScheme with Diagnosticable {
// surfaceVariant and inverseSurface on purpose.
surfaceVariant: effectiveSurfaceVariantColor,
inverseSurface: effectiveInverseSurfaceColor,
surfaceTint: surfaceTint,
) ??
// We had a colorScheme passed in, we use as passed in, but set
// override values for props we have not handled via FCS direct
Expand Down

0 comments on commit 2249169

Please sign in to comment.