如何使用Animations包的SharedAxisTransition实现Flutter动画Stepper效果
问题根源
你当前的写法将完整Stepper组件作为PageTransitionSwitcher的子元素,当stepperIndex变更时会触发整个Stepper参与过渡重建,因此左侧的步骤指示器、垂直分割线都会跟着动画,不符合需求。
解决方案
核心逻辑是仅对Step的content内容区域做过渡,保留Stepper框架部分(指示器、分割线)的原有状态不参与动画,具体实现如下:
- 新增变量记录步进方向,用于控制过渡动画的播放方向,符合前进/后退的交互直觉
- 改造Step列表的生成逻辑,仅当前激活的Step返回带过渡动画的内容,其余Step返回空占位组件
- 移除外层包裹Stepper的PageTransitionSwitcher,避免整个组件参与过渡
完整实现代码
import 'package:animations/animations.dart'; class AnimatedStepperPage extends StatefulWidget { const AnimatedStepperPage({super.key}); @override State<AnimatedStepperPage> createState() => _AnimatedStepperPageState(); } class _AnimatedStepperPageState extends State<AnimatedStepperPage> { int _currentStep = 0; // 记录步进方向:前进为true,后退为false bool _isForward = true; // 生成每个步骤的自定义内容 Widget _buildStepContent(int stepIndex) { return Container( alignment: Alignment.centerLeft, padding: const EdgeInsets.symmetric(vertical: 16), child: Text('这是步骤 ${stepIndex + 1} 的内容'), ); } List<Step> get _steps => List.generate(3, (index) => Step( title: Text('步骤 ${index + 1}'), // 仅当前激活的步骤返回带过渡的内容,其余返回空占位 content: index == _currentStep ? PageTransitionSwitcher( duration: const Duration(milliseconds: 300), reverse: !_isForward, transitionBuilder: (child, animation, secondaryAnimation) => SharedAxisTransition( transitionType: SharedAxisTransitionType.vertical, animation: animation, secondaryAnimation: secondaryAnimation, child: child, ), child: _buildStepContent(index, key: ValueKey(index)), ) : const SizedBox.shrink(), isActive: index <= _currentStep, )); void _handleStepContinue() { if (_currentStep < _steps.length - 1) { setState(() { _isForward = true; _currentStep += 1; }); } } void _handleStepCancel() { if (_currentStep > 0) { setState(() { _isForward = false; _currentStep -= 1; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: const FliAppBar(), body: Stepper( currentStep: _currentStep, steps: _steps, onStepContinue: _handleStepContinue, onStepCancel: _handleStepCancel, ), ); } }
效果优化说明
如果需要调整内容区域的边距、分割线样式,可以通过Theme组件包裹Stepper,修改stepperTheme的相关配置即可,不会影响过渡动画的生效。
内容的提问来源于stack exchange,提问作者swedishcheef
相关产品推荐
相关产品推荐

