Flutter状态切换时如何为Column中不同状态类渲染的子组件添加动画
核心问题为以下两点导致AnimatedSwitcher失效:
- 给StreamBuilder设置了随状态变化的ValueKey,每次状态切换时StreamBuilder会直接重建,没有给动画留下执行时机
- AnimatedSwitcher需要直接包裹要切换的子组件,且子组件需要携带和当前状态绑定的唯一Key,才能检测到组件变化触发动画
代码修改方案
- 移除StreamBuilder上的动态Key
- 在StreamBuilder的builder方法中嵌套AnimatedSwitcher,将状态类render返回的组件作为AnimatedSwitcher的child,同时给child绑定和当前状态对应的唯一Key
- 自定义transitionBuilder实现所需的尺寸变化动画效果
修改后的代码示例如下:
@override Widget build(BuildContext context) { return ScrollConfiguration( behavior: ScrollBehavior(), child: SingleChildScrollView( padding: const EdgeInsets.all(8.0), child: Column(children: [ ElevatedButton( child: const Text("Change State"), onPressed: () { state1 = !state1; _changeState(state1 ? State1() : State2()); }, ), const SizedBox(height: 100), // 移除原有的动态Key StreamBuilder( initialData: State1(), stream: _stateContext.outState, builder: (_, AsyncSnapshot<IState> snapshot) { final currentStateWidget = snapshot.data!.render(); return AnimatedSwitcher( duration: const Duration(milliseconds: 300), // 自定义尺寸变化动画,可按需叠加淡入淡出等其他动画效果 transitionBuilder: (child, animation) { return SizeTransition( sizeFactor: animation, child: child, ); }, // 给子组件绑定和当前状态对应的唯一Key child: KeyedSubtree( key: ValueKey(snapshot.data.runtimeType), child: currentStateWidget, ), ); }, ), ]), ), ); }
如果两个状态返回的红色盒子是同一组件仅属性不同,也可直接将尺寸参数存入状态类,通过AnimatedContainer实现更丝滑的尺寸过渡,无需依赖AnimatedSwitcher。如果是完全不同的组件结构,上述AnimatedSwitcher方案即可满足需求。
内容的提问来源于stack exchange,提问作者Raghu N
相关产品推荐
相关产品推荐

