diff --git a/packages/flutter/lib/src/material/ink_ripple.dart b/packages/flutter/lib/src/material/ink_ripple.dart index 83fbceeb908..2cff59abf24 100644 --- a/packages/flutter/lib/src/material/ink_ripple.dart +++ b/packages/flutter/lib/src/material/ink_ripple.dart @@ -237,28 +237,16 @@ class InkRipple extends InteractiveInkFeature { referenceBox.size.center(Offset.zero), Curves.ease.transform(_radiusController.value), ); - final Offset originOffset = MatrixUtils.getAsTranslation(transform); - canvas.save(); - if (originOffset == null) { - canvas.transform(transform.storage); - } else { - canvas.translate(originOffset.dx, originOffset.dy); - } - if (_clipCallback != null) { - final Rect rect = _clipCallback(); - if (_customBorder != null) { - canvas.clipPath(_customBorder.getOuterPath(rect, textDirection: _textDirection)); - } else if (_borderRadius != BorderRadius.zero) { - canvas.clipRRect(RRect.fromRectAndCorners( - rect, - topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight, - bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight, - )); - } else { - canvas.clipRect(rect); - } - } - canvas.drawCircle(center, _radius.value, paint); - canvas.restore(); + paintInkCircle( + canvas: canvas, + transform: transform, + paint: paint, + center: center, + textDirection: _textDirection, + radius: _radius.value, + customBorder: _customBorder, + borderRadius: _borderRadius, + clipCallback: _clipCallback, + ); } } diff --git a/packages/flutter/lib/src/material/ink_splash.dart b/packages/flutter/lib/src/material/ink_splash.dart index 117e7b7aff7..68ad70ec01b 100644 --- a/packages/flutter/lib/src/material/ink_splash.dart +++ b/packages/flutter/lib/src/material/ink_splash.dart @@ -202,28 +202,16 @@ class InkSplash extends InteractiveInkFeature { Offset center = _position; if (_repositionToReferenceBox) center = Offset.lerp(center, referenceBox.size.center(Offset.zero), _radiusController.value); - final Offset originOffset = MatrixUtils.getAsTranslation(transform); - canvas.save(); - if (originOffset == null) { - canvas.transform(transform.storage); - } else { - canvas.translate(originOffset.dx, originOffset.dy); - } - if (_clipCallback != null) { - final Rect rect = _clipCallback(); - if (_customBorder != null) { - canvas.clipPath(_customBorder.getOuterPath(rect, textDirection: _textDirection)); - } else if (_borderRadius != BorderRadius.zero) { - canvas.clipRRect(RRect.fromRectAndCorners( - rect, - topLeft: _borderRadius.topLeft, topRight: _borderRadius.topRight, - bottomLeft: _borderRadius.bottomLeft, bottomRight: _borderRadius.bottomRight, - )); - } else { - canvas.clipRect(rect); - } - } - canvas.drawCircle(center, _radius.value, paint); - canvas.restore(); + paintInkCircle( + canvas: canvas, + transform: transform, + paint: paint, + center: center, + textDirection: _textDirection, + radius: _radius.value, + customBorder: _customBorder, + borderRadius: _borderRadius, + clipCallback: _clipCallback, + ); } } diff --git a/packages/flutter/lib/src/material/ink_well.dart b/packages/flutter/lib/src/material/ink_well.dart index 551e6c1e5da..f5c227da47d 100644 --- a/packages/flutter/lib/src/material/ink_well.dart +++ b/packages/flutter/lib/src/material/ink_well.dart @@ -64,6 +64,80 @@ abstract class InteractiveInkFeature extends InkFeature { _color = value; controller.markNeedsPaint(); } + + /// Draws an ink splash or ink ripple on the passed in [Canvas]. + /// + /// The [transform] argument is the [Matrix4] transform that typically + /// shifts the coordinate space of the canvas to the space in which + /// the ink circle is to be painted. + /// + /// [center] is the [Offset] from origin of the canvas where the center + /// of the circle is drawn. + /// + /// [paint] takes a [Paint] object that describes the styles used to draw the ink circle. + /// For example, [paint] can specify properties like color, strokewidth, colorFilter. + /// + /// [radius] is the radius of ink circle to be drawn on canvas. + /// + /// [clipCallback] is the callback used to obtain the [Rect] used for clipping the ink effect. + /// If [clipCallback] is null, no clipping is performed on the ink circle. + /// + /// Clipping can happen in 3 different ways - + /// 1. If [customBorder] is provided, it is used to determine the path + /// for clipping. + /// 2. If [customBorder] is null, and [borderRadius] is provided, the canvas + /// is clipped by an [RRect] created from [clipCallback] and [borderRadius]. + /// 3. If [borderRadius] is the default [BorderRadius.zero], then the [Rect] provided + /// by [clipCallback] is used for clipping. + /// + /// [textDirection] is used by [customBorder] if it is non-null. This allows the [customBorder]'s path + /// to be properly defined if it was the path was expressed in terms of "start" and "end" instead of + /// "left" and "right". + /// + /// For examples on how the function is used, see [InkSplash] and [InkRipple]. + @protected + void paintInkCircle({ + @required Canvas canvas, + @required Matrix4 transform, + @required Paint paint, + @required Offset center, + @required double radius, + TextDirection textDirection, + ShapeBorder customBorder, + BorderRadius borderRadius = BorderRadius.zero, + RectCallback clipCallback, + }) { + assert(canvas != null); + assert(transform != null); + assert(paint != null); + assert(center != null); + assert(radius != null); + assert(borderRadius != null); + + final Offset originOffset = MatrixUtils.getAsTranslation(transform); + canvas.save(); + if (originOffset == null) { + canvas.transform(transform.storage); + } else { + canvas.translate(originOffset.dx, originOffset.dy); + } + if (clipCallback != null) { + final Rect rect = clipCallback(); + if (customBorder != null) { + canvas.clipPath(customBorder.getOuterPath(rect, textDirection: textDirection)); + } else if (borderRadius != BorderRadius.zero) { + canvas.clipRRect(RRect.fromRectAndCorners( + rect, + topLeft: borderRadius.topLeft, topRight: borderRadius.topRight, + bottomLeft: borderRadius.bottomLeft, bottomRight: borderRadius.bottomRight, + )); + } else { + canvas.clipRect(rect); + } + } + canvas.drawCircle(center, radius, paint); + canvas.restore(); + } } /// An encapsulation of an [InteractiveInkFeature] constructor used by