Created
July 31, 2025 17:17
-
-
Save DerhachevAndrii/9be18815be4bdeaa51e3ff0533032da4 to your computer and use it in GitHub Desktop.
CupertinoHighlight for InkWell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
class _CupertinoSplashFactory extends InteractiveInkFeatureFactory { | |
const _CupertinoSplashFactory(); | |
@override | |
InteractiveInkFeature create({ | |
required MaterialInkController controller, | |
required RenderBox referenceBox, | |
required Offset position, | |
required Color color, | |
required TextDirection textDirection, | |
bool containedInkWell = false, | |
RectCallback? rectCallback, | |
BorderRadius? borderRadius, | |
ShapeBorder? customBorder, | |
double? radius, | |
VoidCallback? onRemoved, | |
}) { | |
return CupertinoHighlight( | |
controller: controller, | |
referenceBox: referenceBox, | |
color: color, | |
textDirection: textDirection, | |
rectCallback: rectCallback, | |
borderRadius: borderRadius, | |
radius: radius, | |
onRemoved: onRemoved, | |
); | |
} | |
} | |
class CupertinoHighlight extends InteractiveInkFeature { | |
static const InteractiveInkFeatureFactory splashFactory = | |
_CupertinoSplashFactory(); | |
CupertinoHighlight({ | |
required super.controller, | |
required super.referenceBox, | |
required super.color, | |
required TextDirection textDirection, | |
BoxShape shape = BoxShape.rectangle, | |
double? radius, | |
BorderRadius? borderRadius, | |
super.customBorder, | |
RectCallback? rectCallback, | |
super.onRemoved, | |
Duration fadeDuration = const Duration(milliseconds: 200), | |
}) : _shape = shape, | |
_radius = radius, | |
_borderRadius = borderRadius ?? BorderRadius.zero, | |
_textDirection = textDirection, | |
_rectCallback = rectCallback { | |
_alphaController = | |
AnimationController(duration: fadeDuration, vsync: controller.vsync) | |
..addListener(controller.markNeedsPaint) | |
..addStatusListener(_handleAlphaStatusChanged) | |
..forward(); | |
_alpha = _alphaController.drive( | |
IntTween( | |
begin: 0, | |
end: color.alpha, | |
), | |
); | |
controller.addInkFeature(this); | |
} | |
final BoxShape _shape; | |
final double? _radius; | |
final BorderRadius _borderRadius; | |
final RectCallback? _rectCallback; | |
final TextDirection _textDirection; | |
late Animation<int> _alpha; | |
late AnimationController _alphaController; | |
bool get active => _active; | |
bool _active = true; | |
void activate() { | |
_active = true; | |
_alphaController.forward(); | |
} | |
void deactivate() { | |
_active = false; | |
_alphaController.reverse(); | |
} | |
void _handleAlphaStatusChanged(AnimationStatus status) { | |
if (status == AnimationStatus.completed) { | |
deactivate(); | |
} else if (status == AnimationStatus.dismissed && !_active) { | |
dispose(); | |
} | |
} | |
@override | |
void dispose() { | |
_alphaController.dispose(); | |
super.dispose(); | |
} | |
@override | |
void paintFeature(Canvas canvas, Matrix4 transform) { | |
final Paint paint = Paint()..color = color.withAlpha(_alpha.value); | |
final Offset? originOffset = MatrixUtils.getAsTranslation(transform); | |
final Rect rect = _rectCallback != null | |
? _rectCallback!() | |
: Offset.zero & referenceBox.size; | |
if (originOffset == null) { | |
canvas.save(); | |
canvas.transform(transform.storage); | |
_paintHighlight(canvas, rect, paint); | |
canvas.restore(); | |
} else { | |
_paintHighlight(canvas, rect.shift(originOffset), paint); | |
} | |
} | |
void _paintHighlight(Canvas canvas, Rect rect, Paint paint) { | |
canvas.save(); | |
if (customBorder != null) { | |
canvas.clipPath( | |
customBorder!.getOuterPath(rect, textDirection: _textDirection), | |
); | |
} | |
switch (_shape) { | |
case BoxShape.circle: | |
canvas.drawCircle( | |
rect.center, | |
_radius ?? Material.defaultSplashRadius, | |
paint, | |
); | |
case BoxShape.rectangle: | |
if (_borderRadius != BorderRadius.zero) { | |
final RRect clipRRect = RRect.fromRectAndCorners( | |
rect, | |
topLeft: _borderRadius.topLeft, | |
topRight: _borderRadius.topRight, | |
bottomLeft: _borderRadius.bottomLeft, | |
bottomRight: _borderRadius.bottomRight, | |
); | |
canvas.drawRRect(clipRRect, paint); | |
} else { | |
canvas.drawRect(rect, paint); | |
} | |
} | |
canvas.restore(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment