Skip to content

Commit ad7322d

Browse files
authored
Hide InkWell hover highlight when an hovered InkWell is disabled (#118026)
1 parent 466cb54 commit ad7322d

File tree

3 files changed

+65
-8
lines changed

3 files changed

+65
-8
lines changed

packages/flutter/lib/src/material/ink_well.dart

+14-7
Original file line numberDiff line numberDiff line change
@@ -842,21 +842,28 @@ class _InkResponseState extends State<_InkResponseStateWidget>
842842
widget.radius != oldWidget.radius ||
843843
widget.borderRadius != oldWidget.borderRadius ||
844844
widget.highlightShape != oldWidget.highlightShape) {
845-
final InkHighlight? hoverHighLight = _highlights[_HighlightType.hover];
846-
if (hoverHighLight != null) {
847-
hoverHighLight.dispose();
845+
final InkHighlight? hoverHighlight = _highlights[_HighlightType.hover];
846+
if (hoverHighlight != null) {
847+
hoverHighlight.dispose();
848848
updateHighlight(_HighlightType.hover, value: _hovering, callOnHover: false);
849849
}
850-
final InkHighlight? focusHighLight = _highlights[_HighlightType.focus];
851-
if (focusHighLight != null) {
852-
focusHighLight.dispose();
850+
final InkHighlight? focusHighlight = _highlights[_HighlightType.focus];
851+
if (focusHighlight != null) {
852+
focusHighlight.dispose();
853853
// Do not call updateFocusHighlights() here because it is called below
854854
}
855855
}
856856
if (enabled != isWidgetEnabled(oldWidget)) {
857857
statesController.update(MaterialState.disabled, !enabled);
858858
if (!enabled) {
859859
statesController.update(MaterialState.pressed, false);
860+
// Remove the existing hover highlight immediately when enabled is false.
861+
// Do not rely on updateHighlight or InkHighlight.deactivate to not break
862+
// the expected lifecycle which is updating _hovering when the mouse exit.
863+
// Manually updating _hovering here or calling InkHighlight.deactivate
864+
// will lead to onHover not being called or call when it is not allowed.
865+
final InkHighlight? hoverHighlight = _highlights[_HighlightType.hover];
866+
hoverHighlight?.dispose();
860867
}
861868
// Don't call widget.onHover because many widgets, including the button
862869
// widgets, apply setState to an ancestor context from onHover.
@@ -937,7 +944,7 @@ class _InkResponseState extends State<_InkResponseStateWidget>
937944
_highlights[type] = InkHighlight(
938945
controller: Material.of(context),
939946
referenceBox: referenceBox,
940-
color: resolvedOverlayColor,
947+
color: enabled ? resolvedOverlayColor : resolvedOverlayColor.withAlpha(0),
941948
shape: widget.highlightShape,
942949
radius: widget.radius,
943950
borderRadius: widget.borderRadius,

packages/flutter/test/material/ink_well_test.dart

+50
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,56 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async {
17221722
expect(hover, false);
17231723
});
17241724

1725+
testWidgets('hovered ink well draws a transparent highlight when disabled', (WidgetTester tester) async {
1726+
Widget buildFrame({ required bool enabled }) {
1727+
return Material(
1728+
child: Directionality(
1729+
textDirection: TextDirection.ltr,
1730+
child: Center(
1731+
child: SizedBox(
1732+
width: 100,
1733+
height: 100,
1734+
child: InkWell(
1735+
onTap: enabled ? () { } : null,
1736+
onHover: (bool value) { },
1737+
hoverColor: const Color(0xff00ff00),
1738+
),
1739+
),
1740+
),
1741+
),
1742+
);
1743+
}
1744+
1745+
await tester.pumpWidget(buildFrame(enabled: true));
1746+
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
1747+
await gesture.addPointer();
1748+
1749+
// Hover the enabled InkWell.
1750+
await gesture.moveTo(tester.getCenter(find.byType(InkWell)));
1751+
await tester.pumpAndSettle();
1752+
expect(
1753+
find.byType(Material),
1754+
paints
1755+
..rect(
1756+
color: const Color(0xff00ff00),
1757+
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
1758+
)
1759+
);
1760+
1761+
// Disable the hovered InkWell.
1762+
await tester.pumpWidget(buildFrame(enabled: false));
1763+
await tester.pumpAndSettle();
1764+
expect(
1765+
find.byType(Material),
1766+
paints
1767+
..rect(
1768+
color: const Color(0x0000ff00),
1769+
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
1770+
)
1771+
);
1772+
});
1773+
1774+
17251775
testWidgets('Changing InkWell.enabled should not trigger TextButton setState()', (WidgetTester tester) async {
17261776
Widget buildFrame({ required bool enabled }) {
17271777
return Material(

packages/flutter/test/material/list_tile_test.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ void main() {
979979
paints
980980
..rect()
981981
..rect(
982-
color: Colors.orange[500],
982+
color: Colors.orange[500]!.withAlpha(0),
983983
rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0),
984984
)
985985
..rect(

0 commit comments

Comments
 (0)