Skip to content

Commit ff347bf

Browse files
authored
Fix InkRipple doesn't respect rectCallback when rendering ink circle (#117395)
1 parent 1970bc9 commit ff347bf

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -232,10 +232,14 @@ class InkRipple extends InteractiveInkFeature {
232232
void paintFeature(Canvas canvas, Matrix4 transform) {
233233
final int alpha = _fadeInController.isAnimating ? _fadeIn.value : _fadeOut.value;
234234
final Paint paint = Paint()..color = color.withAlpha(alpha);
235+
Rect? rect;
236+
if (_clipCallback != null) {
237+
rect = _clipCallback!();
238+
}
235239
// Splash moves to the center of the reference box.
236240
final Offset center = Offset.lerp(
237241
_position,
238-
referenceBox.size.center(Offset.zero),
242+
rect != null ? rect.center : referenceBox.size.center(Offset.zero),
239243
Curves.ease.transform(_radiusController.value),
240244
)!;
241245
paintInkCircle(

packages/flutter/test/material/ink_paint_test.dart

+86
Original file line numberDiff line numberDiff line change
@@ -445,4 +445,90 @@ void main() {
445445
throw 'Expected: paint.color.alpha == 0, found: ${paint.color.alpha}';
446446
}));
447447
});
448+
449+
testWidgets('Custom rectCallback renders an ink splash from its center', (WidgetTester tester) async {
450+
const Color splashColor = Color(0xff00ff00);
451+
452+
Widget buildWidget({InteractiveInkFeatureFactory? splashFactory}) {
453+
return Directionality(
454+
textDirection: TextDirection.ltr,
455+
child: Material(
456+
child: Center(
457+
child: SizedBox(
458+
width: 100.0,
459+
height: 200.0,
460+
child: InkResponse(
461+
splashColor: splashColor,
462+
containedInkWell: true,
463+
highlightShape: BoxShape.rectangle,
464+
splashFactory: splashFactory,
465+
onTap: () { },
466+
),
467+
),
468+
),
469+
),
470+
);
471+
}
472+
473+
await tester.pumpWidget(buildWidget());
474+
475+
final Offset center = tester.getCenter(find.byType(SizedBox));
476+
TestGesture gesture = await tester.startGesture(center);
477+
await tester.pump(); // start gesture
478+
await tester.pumpAndSettle(); // Finish rendering ink splash.
479+
480+
RenderBox box = Material.of(tester.element(find.byType(InkResponse))) as RenderBox;
481+
expect(
482+
box,
483+
paints
484+
..circle(x: 50.0, y: 100.0, color: splashColor)
485+
);
486+
487+
await gesture.up();
488+
489+
await tester.pumpWidget(buildWidget(splashFactory: _InkRippleFactory()));
490+
await tester.pumpAndSettle(); // Finish rendering ink splash.
491+
492+
gesture = await tester.startGesture(center);
493+
await tester.pump(); // start gesture
494+
await tester.pumpAndSettle(); // Finish rendering ink splash.
495+
496+
box = Material.of(tester.element(find.byType(InkResponse))) as RenderBox;
497+
expect(
498+
box,
499+
paints
500+
..circle(x: 50.0, y: 50.0, color: splashColor)
501+
);
502+
});
503+
}
504+
505+
class _InkRippleFactory extends InteractiveInkFeatureFactory {
506+
@override
507+
InteractiveInkFeature create({
508+
required MaterialInkController controller,
509+
required RenderBox referenceBox,
510+
required Offset position,
511+
required Color color,
512+
required TextDirection textDirection,
513+
bool containedInkWell = false,
514+
RectCallback? rectCallback,
515+
BorderRadius? borderRadius,
516+
ShapeBorder? customBorder,
517+
double? radius,
518+
VoidCallback? onRemoved,
519+
}) {
520+
return InkRipple(
521+
controller: controller,
522+
referenceBox: referenceBox,
523+
position: position,
524+
color: color,
525+
containedInkWell: containedInkWell,
526+
rectCallback: () => Offset.zero & const Size(100, 100),
527+
borderRadius: borderRadius,
528+
customBorder: customBorder,
529+
radius: radius,
530+
onRemoved: onRemoved,
531+
textDirection: textDirection,
532+
);
533+
}
448534
}

0 commit comments

Comments
 (0)