mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fixed one-frame InkWell overlay color problem on unhover (#111112)
This commit is contained in:
parent
5cd3778875
commit
dc6ab62696
@ -857,22 +857,6 @@ class _InkResponseState extends State<_InkResponseStateWidget>
|
||||
@override
|
||||
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) {
|
||||
switch (type) {
|
||||
case _HighlightType.pressed:
|
||||
@ -911,13 +895,30 @@ class _InkResponseState extends State<_InkResponseStateWidget>
|
||||
if (value == (highlight != null && highlight.active)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
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;
|
||||
_highlights[type] = InkHighlight(
|
||||
controller: Material.of(context)!,
|
||||
referenceBox: referenceBox,
|
||||
color: getHighlightColorForType(type),
|
||||
color: resolvedOverlayColor,
|
||||
shape: widget.highlightShape,
|
||||
radius: widget.radius,
|
||||
borderRadius: widget.borderRadius,
|
||||
@ -1159,6 +1160,25 @@ class _InkResponseState extends State<_InkResponseStateWidget>
|
||||
Widget build(BuildContext context) {
|
||||
assert(widget.debugCheckContext(context));
|
||||
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) {
|
||||
_highlights[type]?.color = getHighlightColorForType(type);
|
||||
}
|
||||
|
||||
@ -1556,4 +1556,42 @@ void main() {
|
||||
expect(tapCount, 3);
|
||||
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)));
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user