如何实现带滑入淡出动画的Flutter Spinbox选择组件
要实现你需要的文本滑入滑出+淡入淡出切换效果,我们可以用Flutter自带的AnimatedSwitcher组件,配合SlideTransition+FadeTransition组合实现,具体修改方案如下:
核心改动说明
- 新增方向控制变量:在State类中新增变量记录当前是切到下一项还是上一项,用来决定滑动的方向
- 替换原有Text组件:用
AnimatedSwitcher包裹文本区域,自定义过渡动画实现淡入+滑动效果 - 绑定唯一Key:给文本组件绑定和当前索引关联的Key,让AnimatedSwitcher可以识别内容变更触发动画
修改后完整代码
只需要替换原有的_SpinBoxState类代码即可:
class _SpinBoxState<T> extends State<SpinBox<T>> { int _currentIndex = 0; // 新增变量记录切换方向,true为切下一项,false为切上一项 bool _isNextDirection = true; @override void initState() { _currentIndex = widget.defaultIndex; super.initState(); } void _next() { if (_currentIndex < widget.length - 1) { _isNextDirection = true; setState(() { _currentIndex++; widget.onChange?.call(widget.values[_currentIndex]); }); } } void _prev() { if (_currentIndex > 0) { _isNextDirection = false; setState(() { _currentIndex--; widget.onChange?.call(widget.values[_currentIndex]); }); } } @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: _prev, icon: FaIcon(FontAwesomeIcons.caretLeft)), Expanded( // 用AnimatedSwitcher包裹文本区域 child: AnimatedSwitcher( duration: const Duration(milliseconds: 200), // 自定义过渡动画:淡入淡出+滑动 transitionBuilder: (Widget child, Animation<double> animation) { // 滑动偏移量:切下一项时新内容从右侧进入,旧内容向左离开;切上一项时相反 final offsetAnimation = Tween<Offset>( begin: _isNextDirection ? const Offset(1.0, 0.0) : const Offset(-1.0, 0.0), end: Offset.zero, ).animate(animation); // 组合淡入+滑动效果 return FadeTransition( opacity: animation, child: SlideTransition( position: offsetAnimation, child: child, ), ); }, // 必须给子组件加唯一key,才能触发动画 child: Text( widget.labels[_currentIndex], key: ValueKey<int>(_currentIndex), textAlign: TextAlign.center, ), ), ), IconButton( onPressed: _next, icon: FaIcon(FontAwesomeIcons.caretRight)), ], ); } }
如果需要调整动画速度,修改AnimatedSwitcher的duration参数即可,也可以通过CurvedAnimation自定义动画的速率曲线。
内容的提问来源于stack exchange,提问作者Ushyme
相关产品推荐
相关产品推荐

