Flutter中如何实现文本删除线动画效果?
在Flutter中实现待办任务的删除线动画效果
要实现删除线从左到右平滑划过的动画效果,你可以通过自定义带动画的文本组件来实现,以下是具体方案:
实现步骤
1. 自定义带动画删除线的TaskText组件
创建一个StatefulWidget,结合动画控制器和自定义裁剪器,实现删除线的渐进式显示/隐藏:
class TaskText extends StatefulWidget { final String title; final bool isDone; final TextStyle style; const TaskText({ super.key, required this.title, required this.isDone, required this.style, }); @override State<TaskText> createState() => _TaskTextState(); } class _TaskTextState extends State<TaskText> with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation<double> _lineAnimation; late Animation<Color?> _colorAnimation; @override void initState() { super.initState(); // 初始化动画控制器,设置动画时长 _animationController = AnimationController( duration: const Duration(milliseconds: 500), vsync: this, ); // 删除线进度动画:从0到1 _lineAnimation = Tween<double>(begin: 0, end: 1).animate( CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), ); // 文本颜色渐变动画:从原始色到灰色 _colorAnimation = ColorTween( begin: widget.style.color, end: Colors.grey, ).animate(_animationController); // 初始状态为已完成时,直接完成动画 if (widget.isDone) { _animationController.forward(); } } @override void didUpdateWidget(covariant TaskText oldWidget) { super.didUpdateWidget(oldWidget); // 监听isDone状态变化,触发动画 if (widget.isDone != oldWidget.isDone) { widget.isDone ? _animationController.forward() : _animationController.reverse(); } } @override void dispose() { _animationController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Stack( children: [ // 显示原始文本,颜色随动画渐变 Text( widget.title, overflow: TextOverflow.ellipsis, style: widget.style.copyWith( decoration: TextDecoration.none, color: _colorAnimation.value, ), ), // 动画删除线:通过裁剪容器实现渐进显示 AnimatedBuilder( animation: _lineAnimation, builder: (context, child) { return ClipPath( clipper: _LineClipper(progress: _lineAnimation.value), child: child, ); }, child: Container( height: 2, // 调整删除线的垂直位置,适配字体大小 margin: EdgeInsets.only(top: widget.style.fontSize! * 0.7), color: Colors.grey, ), ), ], ); } } // 自定义裁剪器,根据动画进度控制删除线的显示范围 class _LineClipper extends CustomClipper<Path> { final double progress; _LineClipper({required this.progress}); @override Path getClip(Size size) { final path = Path(); path.lineTo(size.width * progress, 0); path.lineTo(size.width * progress, size.height); path.lineTo(0, size.height); path.close(); return path; } @override bool shouldReclip(covariant _LineClipper oldClipper) { return progress != oldClipper.progress; } }
2. 替换原有Text组件
将你原来的Text.rich替换为自定义的TaskText:
TaskText( title: task.title, isDone: task.isDone, style: const TextStyle( fontFamily: 'Helvatica_lite', fontWeight: FontWeight.bold, fontSize: 15, color: Colors.black, ), );
效果说明
- 当
task.isDone变为true时,删除线会从左到右平滑划过,同时文本颜色逐渐变为灰色 - 当
task.isDone变为false时,删除线会从右到左隐藏,文本颜色恢复为黑色 - 动画时长可通过修改
AnimationController的duration参数调整
内容的提问来源于stack exchange,提问作者mishalhaneef
相关产品推荐
相关产品推荐

