我无法在Flutter中复制普通设置菜单。我正在使用InkWell尝试创建通常在您点击设置选项时发生的飞溅效果。问题在于,飞溅效果与正常情况相比显得太快了。基本上,我只想放慢InkWell的速度。
可以创建所需的内容,但需要splashFactory在InkWell类下进行自定义。
splashFactory
InkWell
正如您在下面的变量中看到的那样,这些变量是私有值,并且不允许在类内进行修改。
const Duration _kUnconfirmedSplashDuration = const Duration(seconds: 1); const Duration _kSplashFadeDuration = const Duration(milliseconds: 200); const double _kSplashInitialSize = 0.0; // logical pixels const double _kSplashConfirmedVelocity = 1.0;
要回答您的问题,可以的。我只是复制并粘贴了源代码中的所有内容,然后更改了动画值。在下面的代码之后,只需在中使用它即可splashFactory。
///Part to use within application new InkWell( onTap: () {}, splashFactory: CustomSplashFactory(), child: Container( padding: EdgeInsets.all(12.0), child: Text('Flat Button'), ), //Part to copy from the source code. const Duration _kUnconfirmedSplashDuration = const Duration(seconds: 10); const Duration _kSplashFadeDuration = const Duration(seconds: 2); const double _kSplashInitialSize = 0.0; // logical pixels const double _kSplashConfirmedVelocity = 0.1; class CustomSplashFactory extends InteractiveInkFeatureFactory { const CustomSplashFactory(); @override InteractiveInkFeature create({ @required MaterialInkController controller, @required RenderBox referenceBox, @required Offset position, @required Color color, bool containedInkWell = false, RectCallback rectCallback, BorderRadius borderRadius, double radius, VoidCallback onRemoved, }) { return new CustomSplash( controller: controller, referenceBox: referenceBox, position: position, color: color, containedInkWell: containedInkWell, rectCallback: rectCallback, borderRadius: borderRadius, radius: radius, onRemoved: onRemoved, ); } } class CustomSplash extends InteractiveInkFeature { /// Used to specify this type of ink splash for an [InkWell], [InkResponse] /// or material [Theme]. static const InteractiveInkFeatureFactory splashFactory = const CustomSplashFactory(); /// Begin a splash, centered at position relative to [referenceBox]. /// /// The [controller] argument is typically obtained via /// `Material.of(context)`. /// /// If `containedInkWell` is true, then the splash will be sized to fit /// the well rectangle, then clipped to it when drawn. The well /// rectangle is the box returned by `rectCallback`, if provided, or /// otherwise is the bounds of the [referenceBox]. /// /// If `containedInkWell` is false, then `rectCallback` should be null. /// The ink splash is clipped only to the edges of the [Material]. /// This is the default. /// /// When the splash is removed, `onRemoved` will be called. CustomSplash({ @required MaterialInkController controller, @required RenderBox referenceBox, Offset position, Color color, bool containedInkWell = false, RectCallback rectCallback, BorderRadius borderRadius, double radius, VoidCallback onRemoved, }) : _position = position, _borderRadius = borderRadius ?? BorderRadius.zero, _targetRadius = radius ?? _getTargetRadius(referenceBox, containedInkWell, rectCallback, position), _clipCallback = _getClipCallback(referenceBox, containedInkWell, rectCallback), _repositionToReferenceBox = !containedInkWell, super(controller: controller, referenceBox: referenceBox, color: color, onRemoved: onRemoved) { assert(_borderRadius != null); _radiusController = new AnimationController(duration: _kUnconfirmedSplashDuration, vsync: controller.vsync) ..addListener(controller.markNeedsPaint) ..forward(); _radius = new Tween<double>( begin: _kSplashInitialSize, end: _targetRadius ).animate(_radiusController); _alphaController = new AnimationController(duration: _kSplashFadeDuration, vsync: controller.vsync) ..addListener(controller.markNeedsPaint) ..addStatusListener(_handleAlphaStatusChanged); _alpha = new IntTween( begin: color.alpha, end: 0 ).animate(_alphaController); controller.addInkFeature(this); } final Offset _position; final BorderRadius _borderRadius; final double _targetRadius; final RectCallback _clipCallback; final bool _repositionToReferenceBox; Animation<double> _radius; AnimationController _radiusController; Animation<int> _alpha; AnimationController _alphaController; @override void confirm() { final int duration = (_targetRadius / _kSplashConfirmedVelocity).floor(); _radiusController ..duration = new Duration(milliseconds: duration) ..forward(); _alphaController.forward(); } @override void cancel() { _alphaController?.forward(); } void _handleAlphaStatusChanged(AnimationStatus status) { if (status == AnimationStatus.completed) dispose(); } @override void dispose() { _radiusController.dispose(); _alphaController.dispose(); _alphaController = null; 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 void paintFeature(Canvas canvas, Matrix4 transform) { final Paint paint = new Paint()..color = color.withAlpha(_alpha.value); Offset center = _position; if (_repositionToReferenceBox) center = Offset.lerp(center, referenceBox.size.center(Offset.zero), _radiusController.value); final Offset originOffset = MatrixUtils.getAsTranslation(transform); if (originOffset == null) { canvas.save(); canvas.transform(transform.storage); if (_clipCallback != null) { _clipCanvasWithRect(canvas, _clipCallback()); } canvas.drawCircle(center, _radius.value, paint); canvas.restore(); } else { if (_clipCallback != null) { canvas.save(); _clipCanvasWithRect(canvas, _clipCallback(), offset: originOffset); } canvas.drawCircle(center + originOffset, _radius.value, paint); if (_clipCallback != null) canvas.restore(); } } } double _getTargetRadius(RenderBox referenceBox, bool containedInkWell, RectCallback rectCallback, Offset position) { if (containedInkWell) { final Size size = rectCallback != null ? rectCallback().size : referenceBox.size; return _getSplashRadiusForPositionInSize(size, position); } return Material.defaultSplashRadius; } double _getSplashRadiusForPositionInSize(Size bounds, Offset position) { final double d1 = (position - bounds.topLeft(Offset.zero)).distance; final double d2 = (position - bounds.topRight(Offset.zero)).distance; final double d3 = (position - bounds.bottomLeft(Offset.zero)).distance; final double d4 = (position - bounds.bottomRight(Offset.zero)).distance; return math.max(math.max(d1, d2), math.max(d3, d4)).ceilToDouble(); } RectCallback _getClipCallback(RenderBox referenceBox, bool containedInkWell, RectCallback rectCallback) { if (rectCallback != null) { assert(containedInkWell); return rectCallback; } if (containedInkWell) return () => Offset.zero & referenceBox.size; return null; }