Last active
September 11, 2021 21:25
-
-
Save caseycrogers/fa310b6e1cfae9caac8c968f726c99f7 to your computer and use it in GitHub Desktop.
Implementation of adaptive color
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
enum AdaptiveColor { | |
primary, | |
secondary, | |
background, | |
surface, | |
} | |
class AdaptiveMaterial extends StatelessWidget { | |
AdaptiveMaterial({ | |
required this.adaptiveColor, | |
required this.child, | |
}); | |
final AdaptiveColor adaptiveColor; | |
final Widget? child; | |
@override | |
Widget build(BuildContext context) { | |
return _ColorProvider<_OnColor>( | |
adaptiveColor, | |
_ColorProvider<_Color>( | |
adaptiveColor, | |
Material( | |
color: _toColor(context, adaptiveColor), | |
child: child, | |
), | |
_toColor(context, adaptiveColor), | |
), | |
_toOnColor(context, adaptiveColor), | |
); | |
} | |
static Color? colorOf(BuildContext context) { | |
final _ColorProvider? result = | |
context.dependOnInheritedWidgetOfExactType<_ColorProvider<_Color>>(); | |
if (result == null) { | |
return null; | |
} | |
return result._colorFromScheme; | |
} | |
static Color? onColorOf(BuildContext context) { | |
final _ColorProvider? result = | |
context.dependOnInheritedWidgetOfExactType<_ColorProvider<_OnColor>>(); | |
if (result == null) { | |
return null; | |
} | |
return result._colorFromScheme; | |
} | |
static Color _toColor( | |
BuildContext context, | |
AdaptiveColor adaptiveColor, | |
) { | |
switch (adaptiveColor) { | |
case AdaptiveColor.primary: | |
return Theme.of(context).colorScheme.primary; | |
case AdaptiveColor.secondary: | |
return Theme.of(context).colorScheme.secondary; | |
case AdaptiveColor.background: | |
return Theme.of(context).colorScheme.background; | |
case AdaptiveColor.surface: | |
return Theme.of(context).colorScheme.surface; | |
} | |
} | |
static Color _toOnColor( | |
BuildContext context, | |
AdaptiveColor adaptiveColor, | |
) { | |
switch (adaptiveColor) { | |
case AdaptiveColor.primary: | |
return Theme.of(context).colorScheme.onPrimary; | |
case AdaptiveColor.secondary: | |
return Theme.of(context).colorScheme.onSecondary; | |
case AdaptiveColor.background: | |
return Theme.of(context).colorScheme.onBackground; | |
case AdaptiveColor.surface: | |
return Theme.of(context).colorScheme.onSurface; | |
} | |
} | |
} | |
abstract class _ColorProviderType {} | |
class _Color implements _ColorProviderType {} | |
class _OnColor implements _ColorProviderType {} | |
class _ColorProvider<T extends _ColorProviderType> extends InheritedWidget { | |
final AdaptiveColor adaptiveColor; | |
final Widget child; | |
final Color _colorFromScheme; | |
_ColorProvider( | |
this.adaptiveColor, | |
this.child, | |
this._colorFromScheme, | |
) : super(child: child); | |
@override | |
bool updateShouldNotify(covariant _ColorProvider oldWidget) { | |
return oldWidget.adaptiveColor != adaptiveColor || | |
oldWidget._colorFromScheme != _colorFromScheme; | |
} | |
} | |
class AdaptiveIconButton extends StatelessWidget { | |
const AdaptiveIconButton({ | |
Key? key, | |
this.iconSize = 24.0, | |
this.visualDensity, | |
this.padding = const EdgeInsets.all(8.0), | |
this.alignment = Alignment.center, | |
this.splashRadius, | |
this.focusColor, | |
this.hoverColor, | |
this.highlightColor, | |
this.splashColor, | |
this.disabledColor, | |
required this.onPressed, | |
this.mouseCursor = SystemMouseCursors.click, | |
this.focusNode, | |
this.autofocus = false, | |
this.tooltip, | |
this.enableFeedback = true, | |
this.constraints, | |
required this.icon, | |
}) : super(key: key); | |
final double iconSize; | |
final VisualDensity? visualDensity; | |
final EdgeInsets padding; | |
final Alignment alignment; | |
final double? splashRadius; | |
final Color? focusColor; | |
final Color? hoverColor; | |
final Color? highlightColor; | |
final Color? splashColor; | |
final Color? disabledColor; | |
final VoidCallback? onPressed; | |
final MouseCursor mouseCursor; | |
final FocusNode? focusNode; | |
final bool autofocus; | |
final String? tooltip; | |
final bool enableFeedback; | |
final BoxConstraints? constraints; | |
final Widget icon; | |
@override | |
Widget build(BuildContext context) { | |
final Color? onColor = AdaptiveMaterial.onColorOf(context); | |
assert( | |
onColor != null, | |
'The current `context` did not contain a parent `AdaptiveColor`. To use ' | |
'and adaptive widget, place an `AdaptiveColor` widget above this one in ' | |
'the widget tree.', | |
); | |
return IconButton( | |
iconSize: iconSize, | |
visualDensity: visualDensity, | |
padding: padding, | |
alignment: alignment, | |
splashRadius: splashRadius, | |
color: onColor, | |
/// TODO(caseycrogers): These colors should reflect `onColor` too. | |
focusColor: focusColor, | |
hoverColor: hoverColor, | |
highlightColor: highlightColor, | |
splashColor: splashColor, | |
disabledColor: disabledColor, | |
onPressed: onPressed, | |
mouseCursor: mouseCursor, | |
focusNode: focusNode, | |
autofocus: autofocus, | |
tooltip: tooltip, | |
enableFeedback: enableFeedback, | |
constraints: constraints, | |
icon: icon, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment