import 'package:flutter/material.dart'; class RippleAnimation extends StatefulWidget { final Widget child; final Duration delay; final Duration duration; final double? maxRadius; final double startScale; const RippleAnimation({ Key? key, required this.child, this.delay = Duration.zero, this.duration = const Duration(milliseconds: 1800), this.maxRadius, this.startScale = 0.0, }) : super(key: key); @override _RippleAnimationState createState() => _RippleAnimationState(); } // 自定义曲线,让动画从 startScale 开始 class _StartScaleCurve extends Curve { final double startScale; _StartScaleCurve(this.startScale); @override double transformInternal(double t) { // t 的范围是 [0.0, 1.0] // 我们将这个范围映射到 [startScale, 1.0] return startScale + (1.0 - startScale) * t; } } class _RippleAnimationState extends State with TickerProviderStateMixin { late AnimationController _controller; late Animation _scaleAnimation; late Animation _fadeAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: widget.duration, vsync: this, ); // 核心改动:使用自定义的曲线 _scaleAnimation = _controller.drive( CurveTween(curve: _StartScaleCurve(widget.startScale)), ); // 淡出动画在后半程开始 _fadeAnimation = Tween(begin: 1.0, end: 0.0).animate( CurvedAnimation(parent: _controller, curve: const Interval(0.5, 1.0)), ); Future.delayed(widget.delay, () { if (mounted) { _controller.repeat(); } }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.scale( scale: _scaleAnimation.value, child: Opacity( opacity: _fadeAnimation.value, child: SizedBox.fromSize( size: widget.maxRadius != null ? Size.square(widget.maxRadius! * 2) : null, child: widget.child, ), ), ); }, ); } }