Unverified Commit dc6ab626 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Fixed one-frame InkWell overlay color problem on unhover (#111112)

parent 5cd37788
...@@ -857,22 +857,6 @@ class _InkResponseState extends State<_InkResponseStateWidget> ...@@ -857,22 +857,6 @@ class _InkResponseState extends State<_InkResponseStateWidget>
@override @override
bool get wantKeepAlive => highlightsExist || (_splashes != null && _splashes!.isNotEmpty); bool get wantKeepAlive => highlightsExist || (_splashes != null && _splashes!.isNotEmpty);
Color getHighlightColorForType(_HighlightType type) {
final ThemeData theme = Theme.of(context);
final Color? resolvedOverlayColor = widget.overlayColor?.resolve(statesController.value);
switch (type) {
// The pressed state triggers a ripple (ink splash), per the current
// Material Design spec. A separate highlight is no longer used.
// See https://material.io/design/interaction/states.html#pressed
case _HighlightType.pressed:
return resolvedOverlayColor ?? widget.highlightColor ?? theme.highlightColor;
case _HighlightType.focus:
return resolvedOverlayColor ?? widget.focusColor ?? theme.focusColor;
case _HighlightType.hover:
return resolvedOverlayColor ?? widget.hoverColor ?? theme.hoverColor;
}
}
Duration getFadeDurationForType(_HighlightType type) { Duration getFadeDurationForType(_HighlightType type) {
switch (type) { switch (type) {
case _HighlightType.pressed: case _HighlightType.pressed:
...@@ -911,13 +895,30 @@ class _InkResponseState extends State<_InkResponseStateWidget> ...@@ -911,13 +895,30 @@ class _InkResponseState extends State<_InkResponseStateWidget>
if (value == (highlight != null && highlight.active)) { if (value == (highlight != null && highlight.active)) {
return; return;
} }
if (value) { if (value) {
if (highlight == null) { if (highlight == null) {
Color? resolvedOverlayColor = widget.overlayColor?.resolve(statesController.value);
if (resolvedOverlayColor == null) {
// Use the backwards compatible defaults
final ThemeData theme = Theme.of(context);
switch (type) {
case _HighlightType.pressed:
resolvedOverlayColor = widget.highlightColor ?? theme.highlightColor;
break;
case _HighlightType.focus:
resolvedOverlayColor = widget.focusColor ?? theme.focusColor;
break;
case _HighlightType.hover:
resolvedOverlayColor = widget.hoverColor ?? theme.hoverColor;
break;
}
}
final RenderBox referenceBox = context.findRenderObject()! as RenderBox; final RenderBox referenceBox = context.findRenderObject()! as RenderBox;
_highlights[type] = InkHighlight( _highlights[type] = InkHighlight(
controller: Material.of(context)!, controller: Material.of(context)!,
referenceBox: referenceBox, referenceBox: referenceBox,
color: getHighlightColorForType(type), color: resolvedOverlayColor,
shape: widget.highlightShape, shape: widget.highlightShape,
radius: widget.radius, radius: widget.radius,
borderRadius: widget.borderRadius, borderRadius: widget.borderRadius,
...@@ -1159,6 +1160,25 @@ class _InkResponseState extends State<_InkResponseStateWidget> ...@@ -1159,6 +1160,25 @@ class _InkResponseState extends State<_InkResponseStateWidget>
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(widget.debugCheckContext(context)); assert(widget.debugCheckContext(context));
super.build(context); // See AutomaticKeepAliveClientMixin. super.build(context); // See AutomaticKeepAliveClientMixin.
Color getHighlightColorForType(_HighlightType type) {
const Set<MaterialState> pressed = <MaterialState>{MaterialState.pressed};
const Set<MaterialState> focused = <MaterialState>{MaterialState.focused};
const Set<MaterialState> hovered = <MaterialState>{MaterialState.hovered};
final ThemeData theme = Theme.of(context);
switch (type) {
// The pressed state triggers a ripple (ink splash), per the current
// Material Design spec. A separate highlight is no longer used.
// See https://material.io/design/interaction/states.html#pressed
case _HighlightType.pressed:
return widget.overlayColor?.resolve(pressed) ?? widget.highlightColor ?? theme.highlightColor;
case _HighlightType.focus:
return widget.overlayColor?.resolve(focused) ?? widget.focusColor ?? theme.focusColor;
case _HighlightType.hover:
return widget.overlayColor?.resolve(hovered) ?? widget.hoverColor ?? theme.hoverColor;
}
}
for (final _HighlightType type in _highlights.keys) { for (final _HighlightType type in _highlights.keys) {
_highlights[type]?.color = getHighlightColorForType(type); _highlights[type]?.color = getHighlightColorForType(type);
} }
......
...@@ -1556,4 +1556,42 @@ void main() { ...@@ -1556,4 +1556,42 @@ void main() {
expect(tapCount, 3); expect(tapCount, 3);
expect(pressedCount, 2); expect(pressedCount, 2);
}); });
testWidgets('ink well overlayColor opacity fades from 0xff when hover ends', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/110266
await tester.pumpWidget(Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: SizedBox(
width: 100,
height: 100,
child: InkWell(
overlayColor: MaterialStateProperty.resolveWith<Color?>((Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return const Color(0xff00ff00);
}
return null;
}),
onTap: () { },
onLongPress: () { },
onHover: (bool hover) { },
),
),
),
),
));
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(find.byType(SizedBox)));
await tester.pumpAndSettle();
await gesture.moveTo(const Offset(10, 10)); // fade out the overlay
await tester.pump(); // trigger the fade out animation
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
// Fadeout begins with the MaterialStates.hovered overlay color
expect(inkFeatures, paints..rect(rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0), color: const Color(0xff00ff00)));
// 50ms fadeout is 50% complete, overlay color alpha goes from 0xff to 0x80
await tester.pump(const Duration(milliseconds: 25));
expect(inkFeatures, paints..rect(rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0), color: const Color(0x8000ff00)));
});
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment