InkResponse highlights can be updated (#115635)
Co-authored-by: Bruno Leroux <bruno.leroux@gmail.com>
diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart
index 240d199..8440c91 100644
--- a/packages/flutter/lib/src/material/ink_well.dart
+++ b/packages/flutter/lib/src/material/ink_well.dart
@@ -834,6 +834,21 @@
}
initStatesController();
}
+ if (widget.customBorder != oldWidget.customBorder ||
+ widget.radius != oldWidget.radius ||
+ widget.borderRadius != oldWidget.borderRadius ||
+ widget.highlightShape != oldWidget.highlightShape) {
+ final InkHighlight? hoverHighLight = _highlights[_HighlightType.hover];
+ if (hoverHighLight != null) {
+ hoverHighLight.dispose();
+ updateHighlight(_HighlightType.hover, value: _hovering, callOnHover: false);
+ }
+ final InkHighlight? focusHighLight = _highlights[_HighlightType.focus];
+ if (focusHighLight != null) {
+ focusHighLight.dispose();
+ // Do not call updateFocusHighlights() here because it is called below
+ }
+ }
if (enabled != isWidgetEnabled(oldWidget)) {
statesController.update(MaterialState.disabled, !enabled);
if (!enabled) {
diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart
index 8168aa7..94b3198 100644
--- a/packages/flutter/test/material/ink_well_test.dart
+++ b/packages/flutter/test/material/ink_well_test.dart
@@ -445,6 +445,197 @@
expect(inkFeatures, paints..circle(radius: 20, color: const Color(0xff0000ff)));
});
+ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async {
+ FocusManager.instance.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
+ final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');
+ Widget boilerplate(double radius) {
+ return Material(
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Center(
+ child: SizedBox(
+ width: 100,
+ height: 100,
+ child: InkResponse(
+ focusNode: focusNode,
+ radius: radius,
+ focusColor: const Color(0xff0000ff),
+ onTap: () { },
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+ await tester.pumpWidget(boilerplate(10));
+ await tester.pumpAndSettle();
+ final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 0));
+
+ focusNode.requestFocus();
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 1));
+ expect(inkFeatures, paints..circle(radius: 10, color: const Color(0xff0000ff)));
+
+ await tester.pumpWidget(boilerplate(20));
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 1));
+ expect(inkFeatures, paints..circle(radius: 20, color: const Color(0xff0000ff)));
+ });
+
+ testWidgets('InkResponse highlightShape can be updated', (WidgetTester tester) async {
+ FocusManager.instance.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
+ final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');
+ Widget boilerplate(BoxShape shape) {
+ return Material(
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Center(
+ child: SizedBox(
+ width: 100,
+ height: 100,
+ child: InkResponse(
+ focusNode: focusNode,
+ highlightShape: shape,
+ borderRadius: BorderRadius.circular(10),
+ focusColor: const Color(0xff0000ff),
+ onTap: () { },
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ await tester.pumpWidget(boilerplate(BoxShape.circle));
+ await tester.pumpAndSettle();
+ final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 0));
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 0));
+
+ focusNode.requestFocus();
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 1));
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 0));
+
+ await tester.pumpWidget(boilerplate(BoxShape.rectangle));
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawCircle, 0));
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 1));
+ });
+
+ testWidgets('InkWell borderRadius can be updated', (WidgetTester tester) async {
+ FocusManager.instance.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
+ final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');
+ Widget boilerplate(BorderRadius borderRadius) {
+ return Material(
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Center(
+ child: SizedBox(
+ width: 100,
+ height: 100,
+ child: InkWell(
+ focusNode: focusNode,
+ borderRadius: borderRadius,
+ focusColor: const Color(0xff0000ff),
+ onTap: () { },
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ await tester.pumpWidget(boilerplate(BorderRadius.circular(10)));
+ await tester.pumpAndSettle();
+ final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 0));
+
+ focusNode.requestFocus();
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 1));
+ expect(inkFeatures, paints..rrect(
+ rrect: RRect.fromLTRBR(350.0, 250.0, 450.0, 350.0, const Radius.circular(10)),
+ color: const Color(0xff0000ff),
+ ));
+
+ await tester.pumpWidget(boilerplate(BorderRadius.circular(30)));
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#drawRRect, 1));
+ expect(inkFeatures, paints..rrect(
+ rrect: RRect.fromLTRBR(350.0, 250.0, 450.0, 350.0, const Radius.circular(30)),
+ color: const Color(0xff0000ff),
+ ));
+ });
+
+ testWidgets('InkWell customBorder can be updated', (WidgetTester tester) async {
+ FocusManager.instance.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
+ final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');
+ Widget boilerplate(BorderRadius borderRadius) {
+ return Material(
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: Align(
+ alignment: Alignment.topLeft,
+ child: SizedBox(
+ width: 100,
+ height: 100,
+ child: MouseRegion(
+ child: InkWell(
+ focusNode: focusNode,
+ customBorder: RoundedRectangleBorder(borderRadius: borderRadius),
+ hoverColor: const Color(0xff00ff00),
+ onTap: () { },
+ ),
+ ),
+ ),
+ ),
+ ),
+ );
+ }
+
+ await tester.pumpWidget(boilerplate(BorderRadius.circular(20)));
+ await tester.pumpAndSettle();
+ final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
+ expect(inkFeatures, paintsExactlyCountTimes(#clipPath, 0));
+
+ focusNode.requestFocus();
+ await tester.pumpAndSettle();
+ expect(inkFeatures, paintsExactlyCountTimes(#clipPath, 1));
+
+ const Rect expectedClipRect = Rect.fromLTRB(0, 0, 100, 100);
+ Path expectedClipPath = Path()
+ ..addRRect(RRect.fromRectAndRadius(
+ expectedClipRect,
+ const Radius.circular(20),
+ ));
+ expect(
+ inkFeatures,
+ paints..clipPath(pathMatcher: coversSameAreaAs(
+ expectedClipPath,
+ areaToCompare: expectedClipRect.inflate(20.0),
+ sampleSize: 100,
+ )),
+ );
+
+ await tester.pumpWidget(boilerplate(BorderRadius.circular(40)));
+ await tester.pumpAndSettle();
+ expectedClipPath = Path()
+ ..addRRect(RRect.fromRectAndRadius(
+ expectedClipRect,
+ const Radius.circular(40),
+ ));
+ expect(
+ inkFeatures,
+ paints..clipPath(pathMatcher: coversSameAreaAs(
+ expectedClipPath,
+ areaToCompare: expectedClipRect.inflate(20.0),
+ sampleSize: 100,
+ )),
+ );
+ });
+
testWidgets("ink response doesn't change color on focus when on touch device", (WidgetTester tester) async {
FocusManager.instance.highlightStrategy = FocusHighlightStrategy.alwaysTouch;
final FocusNode focusNode = FocusNode(debugLabel: 'Ink Focus');