Skip to content

Instantly share code, notes, and snippets.

@caseycrogers
Last active September 11, 2021 21:25
Show Gist options
  • Save caseycrogers/fa310b6e1cfae9caac8c968f726c99f7 to your computer and use it in GitHub Desktop.
Save caseycrogers/fa310b6e1cfae9caac8c968f726c99f7 to your computer and use it in GitHub Desktop.
Implementation of adaptive color
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