Unverified Commit ee8754df authored by liyuqian's avatar liyuqian Committed by GitHub

Add customBorder to InkWell so it can clip ShapeBorder (#20751)

This fixes #20483 by letting InkWell do its own clipping.

PathOp.intersect is not used because we have too many unit tests that rely on clipping (e.g., paints..clipXXX()..drawCircle())

The goldens are updated due to small AA changes of the additional clipPath.
parent 363543fc
d0800cf4170e77682173c19703f605c6795e0ff8 cc98e28c974eea0bd9a8e24591857ae6b5479795
...@@ -189,6 +189,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -189,6 +189,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
splashColor: widget.splashColor, splashColor: widget.splashColor,
highlightColor: widget.highlightColor, highlightColor: widget.highlightColor,
onTap: widget.onPressed, onTap: widget.onPressed,
customBorder: widget.shape,
child: IconTheme.merge( child: IconTheme.merge(
data: new IconThemeData(color: widget.textStyle?.color), data: new IconThemeData(color: widget.textStyle?.color),
child: new Container( child: new Container(
......
...@@ -41,12 +41,14 @@ class InkHighlight extends InteractiveInkFeature { ...@@ -41,12 +41,14 @@ class InkHighlight extends InteractiveInkFeature {
@required Color color, @required Color color,
BoxShape shape = BoxShape.rectangle, BoxShape shape = BoxShape.rectangle,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
RectCallback rectCallback, RectCallback rectCallback,
VoidCallback onRemoved, VoidCallback onRemoved,
}) : assert(color != null), }) : assert(color != null),
assert(shape != null), assert(shape != null),
_shape = shape, _shape = shape,
_borderRadius = borderRadius ?? BorderRadius.zero, _borderRadius = borderRadius ?? BorderRadius.zero,
_customBorder = customBorder,
_rectCallback = rectCallback, _rectCallback = rectCallback,
super(controller: controller, referenceBox: referenceBox, color: color, onRemoved: onRemoved) { super(controller: controller, referenceBox: referenceBox, color: color, onRemoved: onRemoved) {
_alphaController = new AnimationController(duration: _kHighlightFadeDuration, vsync: controller.vsync) _alphaController = new AnimationController(duration: _kHighlightFadeDuration, vsync: controller.vsync)
...@@ -63,6 +65,7 @@ class InkHighlight extends InteractiveInkFeature { ...@@ -63,6 +65,7 @@ class InkHighlight extends InteractiveInkFeature {
final BoxShape _shape; final BoxShape _shape;
final BorderRadius _borderRadius; final BorderRadius _borderRadius;
final ShapeBorder _customBorder;
final RectCallback _rectCallback; final RectCallback _rectCallback;
Animation<int> _alpha; Animation<int> _alpha;
...@@ -97,6 +100,10 @@ class InkHighlight extends InteractiveInkFeature { ...@@ -97,6 +100,10 @@ class InkHighlight extends InteractiveInkFeature {
void _paintHighlight(Canvas canvas, Rect rect, Paint paint) { void _paintHighlight(Canvas canvas, Rect rect, Paint paint) {
assert(_shape != null); assert(_shape != null);
canvas.save();
if (_customBorder != null) {
canvas.clipPath(_customBorder.getOuterPath(rect));
}
switch (_shape) { switch (_shape) {
case BoxShape.circle: case BoxShape.circle:
canvas.drawCircle(rect.center, Material.defaultSplashRadius, paint); canvas.drawCircle(rect.center, Material.defaultSplashRadius, paint);
...@@ -114,6 +121,7 @@ class InkHighlight extends InteractiveInkFeature { ...@@ -114,6 +121,7 @@ class InkHighlight extends InteractiveInkFeature {
} }
break; break;
} }
canvas.restore();
} }
@override @override
......
...@@ -48,6 +48,7 @@ class _InkRippleFactory extends InteractiveInkFeatureFactory { ...@@ -48,6 +48,7 @@ class _InkRippleFactory extends InteractiveInkFeatureFactory {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) { }) {
...@@ -59,6 +60,7 @@ class _InkRippleFactory extends InteractiveInkFeatureFactory { ...@@ -59,6 +60,7 @@ class _InkRippleFactory extends InteractiveInkFeatureFactory {
containedInkWell: containedInkWell, containedInkWell: containedInkWell,
rectCallback: rectCallback, rectCallback: rectCallback,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
radius: radius, radius: radius,
onRemoved: onRemoved, onRemoved: onRemoved,
); );
...@@ -115,12 +117,14 @@ class InkRipple extends InteractiveInkFeature { ...@@ -115,12 +117,14 @@ class InkRipple extends InteractiveInkFeature {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) : assert(color != null), }) : assert(color != null),
assert(position != null), assert(position != null),
_position = position, _position = position,
_borderRadius = borderRadius ?? BorderRadius.zero, _borderRadius = borderRadius ?? BorderRadius.zero,
_customBorder = customBorder,
_targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position), _targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position),
_clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback), _clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback),
super(controller: controller, referenceBox: referenceBox, color: color, onRemoved: onRemoved) super(controller: controller, referenceBox: referenceBox, color: color, onRemoved: onRemoved)
...@@ -172,6 +176,7 @@ class InkRipple extends InteractiveInkFeature { ...@@ -172,6 +176,7 @@ class InkRipple extends InteractiveInkFeature {
final Offset _position; final Offset _position;
final BorderRadius _borderRadius; final BorderRadius _borderRadius;
final ShapeBorder _customBorder;
final double _targetRadius; final double _targetRadius;
final RectCallback _clipCallback; final RectCallback _clipCallback;
...@@ -220,26 +225,6 @@ class InkRipple extends InteractiveInkFeature { ...@@ -220,26 +225,6 @@ class InkRipple extends InteractiveInkFeature {
super.dispose(); super.dispose();
} }
RRect _clipRRectFromRect(Rect rect) {
return new RRect.fromRectAndCorners(
rect,
topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight,
bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight,
);
}
void _clipCanvasWithRect(Canvas canvas, Rect rect, {Offset offset}) {
Rect clipRect = rect;
if (offset != null) {
clipRect = clipRect.shift(offset);
}
if (_borderRadius != BorderRadius.zero) {
canvas.clipRRect(_clipRRectFromRect(clipRect));
} else {
canvas.clipRect(clipRect);
}
}
@override @override
void paintFeature(Canvas canvas, Matrix4 transform) { void paintFeature(Canvas canvas, Matrix4 transform) {
final int alpha = _fadeInController.isAnimating ? _fadeIn.value : _fadeOut.value; final int alpha = _fadeInController.isAnimating ? _fadeIn.value : _fadeOut.value;
...@@ -251,22 +236,27 @@ class InkRipple extends InteractiveInkFeature { ...@@ -251,22 +236,27 @@ class InkRipple extends InteractiveInkFeature {
Curves.ease.transform(_radiusController.value), Curves.ease.transform(_radiusController.value),
); );
final Offset originOffset = MatrixUtils.getAsTranslation(transform); final Offset originOffset = MatrixUtils.getAsTranslation(transform);
if (originOffset == null) {
canvas.save(); canvas.save();
if (originOffset == null) {
canvas.transform(transform.storage); canvas.transform(transform.storage);
if (_clipCallback != null) {
_clipCanvasWithRect(canvas, _clipCallback());
}
canvas.drawCircle(center, _radius.value, paint);
canvas.restore();
} else { } else {
canvas.translate(originOffset.dx, originOffset.dy);
}
if (_clipCallback != null) { if (_clipCallback != null) {
canvas.save(); final Rect rect = _clipCallback();
_clipCanvasWithRect(canvas, _clipCallback(), offset: originOffset); if (_customBorder != null) {
canvas.clipPath(_customBorder.getOuterPath(rect));
} else if (_borderRadius != BorderRadius.zero) {
canvas.clipRRect(new RRect.fromRectAndCorners(
rect,
topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight,
bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight,
));
} else {
canvas.clipRect(rect);
} }
canvas.drawCircle(center + originOffset, _radius.value, paint);
if (_clipCallback != null)
canvas.restore();
} }
canvas.drawCircle(center, _radius.value, paint);
canvas.restore();
} }
} }
...@@ -54,6 +54,7 @@ class _InkSplashFactory extends InteractiveInkFeatureFactory { ...@@ -54,6 +54,7 @@ class _InkSplashFactory extends InteractiveInkFeatureFactory {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) { }) {
...@@ -65,6 +66,7 @@ class _InkSplashFactory extends InteractiveInkFeatureFactory { ...@@ -65,6 +66,7 @@ class _InkSplashFactory extends InteractiveInkFeatureFactory {
containedInkWell: containedInkWell, containedInkWell: containedInkWell,
rectCallback: rectCallback, rectCallback: rectCallback,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
radius: radius, radius: radius,
onRemoved: onRemoved, onRemoved: onRemoved,
); );
...@@ -119,10 +121,12 @@ class InkSplash extends InteractiveInkFeature { ...@@ -119,10 +121,12 @@ class InkSplash extends InteractiveInkFeature {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) : _position = position, }) : _position = position,
_borderRadius = borderRadius ?? BorderRadius.zero, _borderRadius = borderRadius ?? BorderRadius.zero,
_customBorder = customBorder,
_targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position), _targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position),
_clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback), _clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback),
_repositionToReferenceBox = !containedInkWell, _repositionToReferenceBox = !containedInkWell,
...@@ -148,6 +152,7 @@ class InkSplash extends InteractiveInkFeature { ...@@ -148,6 +152,7 @@ class InkSplash extends InteractiveInkFeature {
final Offset _position; final Offset _position;
final BorderRadius _borderRadius; final BorderRadius _borderRadius;
final ShapeBorder _customBorder;
final double _targetRadius; final double _targetRadius;
final RectCallback _clipCallback; final RectCallback _clipCallback;
final bool _repositionToReferenceBox; final bool _repositionToReferenceBox;
...@@ -185,26 +190,6 @@ class InkSplash extends InteractiveInkFeature { ...@@ -185,26 +190,6 @@ class InkSplash extends InteractiveInkFeature {
super.dispose(); super.dispose();
} }
RRect _clipRRectFromRect(Rect rect) {
return new RRect.fromRectAndCorners(
rect,
topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight,
bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight,
);
}
void _clipCanvasWithRect(Canvas canvas, Rect rect, {Offset offset}) {
Rect clipRect = rect;
if (offset != null) {
clipRect = clipRect.shift(offset);
}
if (_borderRadius != BorderRadius.zero) {
canvas.clipRRect(_clipRRectFromRect(clipRect));
} else {
canvas.clipRect(clipRect);
}
}
@override @override
void paintFeature(Canvas canvas, Matrix4 transform) { void paintFeature(Canvas canvas, Matrix4 transform) {
final Paint paint = new Paint()..color = color.withAlpha(_alpha.value); final Paint paint = new Paint()..color = color.withAlpha(_alpha.value);
...@@ -212,22 +197,27 @@ class InkSplash extends InteractiveInkFeature { ...@@ -212,22 +197,27 @@ class InkSplash extends InteractiveInkFeature {
if (_repositionToReferenceBox) if (_repositionToReferenceBox)
center = Offset.lerp(center, referenceBox.size.center(Offset.zero), _radiusController.value); center = Offset.lerp(center, referenceBox.size.center(Offset.zero), _radiusController.value);
final Offset originOffset = MatrixUtils.getAsTranslation(transform); final Offset originOffset = MatrixUtils.getAsTranslation(transform);
if (originOffset == null) {
canvas.save(); canvas.save();
if (originOffset == null) {
canvas.transform(transform.storage); canvas.transform(transform.storage);
if (_clipCallback != null) {
_clipCanvasWithRect(canvas, _clipCallback());
}
canvas.drawCircle(center, _radius.value, paint);
canvas.restore();
} else { } else {
canvas.translate(originOffset.dx, originOffset.dy);
}
if (_clipCallback != null) { if (_clipCallback != null) {
canvas.save(); final Rect rect = _clipCallback();
_clipCanvasWithRect(canvas, _clipCallback(), offset: originOffset); if (_customBorder != null) {
canvas.clipPath(_customBorder.getOuterPath(rect));
} else if (_borderRadius != BorderRadius.zero) {
canvas.clipRRect(new RRect.fromRectAndCorners(
rect,
topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight,
bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight,
));
} else {
canvas.clipRect(rect);
} }
canvas.drawCircle(center + originOffset, _radius.value, paint);
if (_clipCallback != null)
canvas.restore();
} }
canvas.drawCircle(center, _radius.value, paint);
canvas.restore();
} }
} }
...@@ -95,6 +95,7 @@ abstract class InteractiveInkFeatureFactory { ...@@ -95,6 +95,7 @@ abstract class InteractiveInkFeatureFactory {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}); });
...@@ -201,6 +202,7 @@ class InkResponse extends StatefulWidget { ...@@ -201,6 +202,7 @@ class InkResponse extends StatefulWidget {
this.highlightShape = BoxShape.circle, this.highlightShape = BoxShape.circle,
this.radius, this.radius,
this.borderRadius, this.borderRadius,
this.customBorder,
this.highlightColor, this.highlightColor,
this.splashColor, this.splashColor,
this.splashFactory, this.splashFactory,
...@@ -285,11 +287,15 @@ class InkResponse extends StatefulWidget { ...@@ -285,11 +287,15 @@ class InkResponse extends StatefulWidget {
/// * [splashFactory], which defines the appearance of the splash. /// * [splashFactory], which defines the appearance of the splash.
final double radius; final double radius;
/// The clipping radius of the containing rect. /// The clipping radius of the containing rect. This is effective only if
/// [customBorder] is null.
/// ///
/// If this is null, it is interpreted as [BorderRadius.zero]. /// If this is null, it is interpreted as [BorderRadius.zero].
final BorderRadius borderRadius; final BorderRadius borderRadius;
/// The custom clip border which overrides [borderRadius].
final ShapeBorder customBorder;
/// The highlight color of the ink response. If this property is null then the /// The highlight color of the ink response. If this property is null then the
/// highlight color of the theme, [ThemeData.highlightColor], will be used. /// highlight color of the theme, [ThemeData.highlightColor], will be used.
/// ///
...@@ -417,6 +423,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe ...@@ -417,6 +423,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe
color: widget.highlightColor ?? Theme.of(context).highlightColor, color: widget.highlightColor ?? Theme.of(context).highlightColor,
shape: widget.highlightShape, shape: widget.highlightShape,
borderRadius: widget.borderRadius, borderRadius: widget.borderRadius,
customBorder: widget.customBorder,
rectCallback: widget.getRectCallback(referenceBox), rectCallback: widget.getRectCallback(referenceBox),
onRemoved: _handleInkHighlightRemoval, onRemoved: _handleInkHighlightRemoval,
); );
...@@ -445,6 +452,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe ...@@ -445,6 +452,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe
final Color color = widget.splashColor ?? Theme.of(context).splashColor; final Color color = widget.splashColor ?? Theme.of(context).splashColor;
final RectCallback rectCallback = widget.containedInkWell ? widget.getRectCallback(referenceBox) : null; final RectCallback rectCallback = widget.containedInkWell ? widget.getRectCallback(referenceBox) : null;
final BorderRadius borderRadius = widget.borderRadius; final BorderRadius borderRadius = widget.borderRadius;
final ShapeBorder customBorder = widget.customBorder;
InteractiveInkFeature splash; InteractiveInkFeature splash;
void onRemoved() { void onRemoved() {
...@@ -466,6 +474,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe ...@@ -466,6 +474,7 @@ class _InkResponseState<T extends InkResponse> extends State<T> with AutomaticKe
rectCallback: rectCallback, rectCallback: rectCallback,
radius: widget.radius, radius: widget.radius,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
onRemoved: onRemoved, onRemoved: onRemoved,
); );
...@@ -626,6 +635,7 @@ class InkWell extends InkResponse { ...@@ -626,6 +635,7 @@ class InkWell extends InkResponse {
InteractiveInkFeatureFactory splashFactory, InteractiveInkFeatureFactory splashFactory,
double radius, double radius,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
bool enableFeedback = true, bool enableFeedback = true,
bool excludeFromSemantics = false, bool excludeFromSemantics = false,
}) : super( }) : super(
...@@ -644,6 +654,7 @@ class InkWell extends InkResponse { ...@@ -644,6 +654,7 @@ class InkWell extends InkResponse {
splashFactory: splashFactory, splashFactory: splashFactory,
radius: radius, radius: radius,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
enableFeedback: enableFeedback, enableFeedback: enableFeedback,
excludeFromSemantics: excludeFromSemantics, excludeFromSemantics: excludeFromSemantics,
); );
......
...@@ -457,7 +457,7 @@ void main() { ...@@ -457,7 +457,7 @@ void main() {
await tester.tap(find.text('B')); await tester.tap(find.text('B'));
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 20)); await tester.pump(const Duration(milliseconds: 20));
expect(box, paints..circle(x: 200.0)..circle(x: 600.0)); expect(box, paints..circle(x: 200.0)..translate(x: 400.0)..circle(x: 200.0));
// Now we flip the directionality and verify that the circles switch positions. // Now we flip the directionality and verify that the circles switch positions.
await tester.pumpWidget( await tester.pumpWidget(
...@@ -478,12 +478,23 @@ void main() { ...@@ -478,12 +478,23 @@ void main() {
), ),
); );
expect(box, paints..circle(x: 600.0)..circle(x: 200.0)); expect(box, paints..translate()..save()..translate(x: 400.0)..circle(x: 200.0)..restore()..circle(x: 200.0));
await tester.tap(find.text('A')); await tester.tap(find.text('A'));
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 20)); await tester.pump(const Duration(milliseconds: 20));
expect(box, paints..circle(x: 600.0)..circle(x: 200.0)..circle(x: 600.0)); expect(
box,
paints
..translate(x: 0.0, y: 0.0)
..save()
..translate(x: 400.0)
..circle(x: 200.0)
..restore()
..circle(x: 200.0)
..translate(x: 400.0)
..circle(x: 200.0)
);
}); });
testWidgets('BottomNavigationBar inactiveIcon shown', (WidgetTester tester) async { testWidgets('BottomNavigationBar inactiveIcon shown', (WidgetTester tester) async {
......
...@@ -40,8 +40,12 @@ void main() { ...@@ -40,8 +40,12 @@ void main() {
expect( expect(
box, box,
paints paints
..clipRRect(rrect: new RRect.fromLTRBR(300.0, 270.0, 500.0, 330.0, const Radius.circular(6.0))) ..translate(x: 0.0, y: 0.0)
..circle(x: 400.0, y: 300.0, radius: 21.0, color: splashColor) ..save()
..translate(x: 300.0, y: 270.0)
..clipRRect(rrect: new RRect.fromLTRBR(0.0, 0.0, 200.0, 60.0, const Radius.circular(6.0)))
..circle(x: 100.0, y: 30.0, radius: 21.0, color: splashColor)
..restore()
..rrect( ..rrect(
rrect: new RRect.fromLTRBR(300.0, 270.0, 500.0, 330.0, const Radius.circular(6.0)), rrect: new RRect.fromLTRBR(300.0, 270.0, 500.0, 330.0, const Radius.circular(6.0)),
color: highlightColor, color: highlightColor,
...@@ -86,93 +90,50 @@ void main() { ...@@ -86,93 +90,50 @@ void main() {
bool offsetsAreClose(Offset a, Offset b) => (a - b).distance < 1.0; bool offsetsAreClose(Offset a, Offset b) => (a - b).distance < 1.0;
bool radiiAreClose(double a, double b) => (a - b).abs() < 1.0; bool radiiAreClose(double a, double b) => (a - b).abs() < 1.0;
// Initially the ripple's center is where the tap occurred, PaintPattern ripplePattern(Offset expectedCenter, double expectedRadius, int expectedAlpha) {
expect(box, paints..something((Symbol method, List<dynamic> arguments) { return paints
..translate(x: 0.0, y: 0.0)
..translate(x: tapDownOffset.dx, y: tapDownOffset.dy)
..something((Symbol method, List<dynamic> arguments) {
if (method != #drawCircle) if (method != #drawCircle)
return false; return false;
final Offset center = arguments[0]; final Offset center = arguments[0];
final double radius = arguments[1]; final double radius = arguments[1];
final Paint paint = arguments[2]; final Paint paint = arguments[2];
if (offsetsAreClose(center, tapDownOffset) && radius == 30.0 && paint.color.alpha == 0) if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == expectedAlpha)
return true; return true;
throw ''' throw '''
Expected: center == $tapDownOffset, radius == 30.0, alpha == 0 Expected: center == $expectedCenter, radius == $expectedRadius, alpha == $expectedAlpha
Found: center == $center radius == $radius alpha == ${paint.color.alpha}'''; Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
})); }
);
}
// Initially the ripple's center is where the tap occurred. Note that
// ripplePattern always add a translation of tapDownOffset.
expect(box, ripplePattern(Offset.zero, 30.0, 0));
// The ripple fades in for 75ms. During that time its alpha is eased from // The ripple fades in for 75ms. During that time its alpha is eased from
// 0 to the splashColor's alpha value and its center moves towards the // 0 to the splashColor's alpha value and its center moves towards the
// center of the ink well. // center of the ink well.
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(box, paints..something((Symbol method, List<dynamic> arguments) { expect(box, ripplePattern(const Offset(17.0, 17.0), 56.0, 120));
if (method != #drawCircle)
return false;
final Offset center = arguments[0];
final double radius = arguments[1];
final Paint paint = arguments[2];
final Offset expectedCenter = tapDownOffset + const Offset(17.0, 17.0);
const double expectedRadius = 56.0;
if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 120)
return true;
throw '''
Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 120
Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
}));
// At 75ms the ripple has fade in: it's alpha matches the splashColor's // At 75ms the ripple has fade in: it's alpha matches the splashColor's
// alpha and its center has moved closer to the ink well's center. // alpha and its center has moved closer to the ink well's center.
await tester.pump(const Duration(milliseconds: 25)); await tester.pump(const Duration(milliseconds: 25));
expect(box, paints..something((Symbol method, List<dynamic> arguments) { expect(box, ripplePattern(const Offset(29.0, 29.0), 73.0, 180));
if (method != #drawCircle)
return false;
final Offset center = arguments[0];
final double radius = arguments[1];
final Paint paint = arguments[2];
final Offset expectedCenter = tapDownOffset + const Offset(29.0, 29.0);
const double expectedRadius = 73.0;
if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 180)
return true;
throw '''
Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 180
Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
}));
// At this point the splash radius has expanded to its limit: 5 past the // At this point the splash radius has expanded to its limit: 5 past the
// ink well's radius parameter. The splash center has moved to its final // ink well's radius parameter. The splash center has moved to its final
// location at the inkwell's center and the fade-out is about to start. // location at the inkwell's center and the fade-out is about to start.
// The fade-out begins at 225ms = 50ms + 25ms + 150ms. // The fade-out begins at 225ms = 50ms + 25ms + 150ms.
await tester.pump(const Duration(milliseconds: 150)); await tester.pump(const Duration(milliseconds: 150));
expect(box, paints..something((Symbol method, List<dynamic> arguments) { expect(box, ripplePattern(inkWellCenter - tapDownOffset, 105.0, 180));
if (method != #drawCircle)
return false;
final Offset center = arguments[0];
final double radius = arguments[1];
final Paint paint = arguments[2];
final Offset expectedCenter = inkWellCenter;
const double expectedRadius = 105.0;
if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 180)
return true;
throw '''
Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 180
Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
}));
// After another 150ms the fade-out is complete. // After another 150ms the fade-out is complete.
await tester.pump(const Duration(milliseconds: 150)); await tester.pump(const Duration(milliseconds: 150));
expect(box, paints..something((Symbol method, List<dynamic> arguments) { expect(box, ripplePattern(inkWellCenter - tapDownOffset, 105.0, 0));
if (method != #drawCircle)
return false;
final Offset center = arguments[0];
final double radius = arguments[1];
final Paint paint = arguments[2];
final Offset expectedCenter = inkWellCenter;
const double expectedRadius = 105.0;
if (offsetsAreClose(center, expectedCenter) && radiiAreClose(radius, expectedRadius) && paint.color.alpha == 0)
return true;
throw '''
Expected: center == $expectedCenter, radius == $expectedRadius, alpha == 0
Found: center == $center radius == $radius alpha == ${paint.color.alpha}''';
}));
}); });
testWidgets('Does the Ink widget render anything', (WidgetTester tester) async { testWidgets('Does the Ink widget render anything', (WidgetTester tester) async {
......
...@@ -19,6 +19,7 @@ class TestInkSplash extends InkSplash { ...@@ -19,6 +19,7 @@ class TestInkSplash extends InkSplash {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) : super( }) : super(
...@@ -29,6 +30,7 @@ class TestInkSplash extends InkSplash { ...@@ -29,6 +30,7 @@ class TestInkSplash extends InkSplash {
containedInkWell: containedInkWell, containedInkWell: containedInkWell,
rectCallback: rectCallback, rectCallback: rectCallback,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
radius: radius, radius: radius,
onRemoved: onRemoved, onRemoved: onRemoved,
); );
...@@ -58,6 +60,7 @@ class TestInkSplashFactory extends InteractiveInkFeatureFactory { ...@@ -58,6 +60,7 @@ class TestInkSplashFactory extends InteractiveInkFeatureFactory {
bool containedInkWell = false, bool containedInkWell = false,
RectCallback rectCallback, RectCallback rectCallback,
BorderRadius borderRadius, BorderRadius borderRadius,
ShapeBorder customBorder,
double radius, double radius,
VoidCallback onRemoved, VoidCallback onRemoved,
}) { }) {
...@@ -69,6 +72,7 @@ class TestInkSplashFactory extends InteractiveInkFeatureFactory { ...@@ -69,6 +72,7 @@ class TestInkSplashFactory extends InteractiveInkFeatureFactory {
containedInkWell: containedInkWell, containedInkWell: containedInkWell,
rectCallback: rectCallback, rectCallback: rectCallback,
borderRadius: borderRadius, borderRadius: borderRadius,
customBorder: customBorder,
radius: radius, radius: radius,
onRemoved: onRemoved, onRemoved: onRemoved,
); );
......
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