如何基于输入在Rive多状态机动画中切换Loading到Error状态?
Flutter Rive状态机无法从Loading切换到Error的解决方案
问题排查与修复步骤
1. 确认输入名称与Rive文件定义完全匹配
检查Rive状态机里的布尔输入名称,确保代码中stateMachineStatus变量的取值和Rive里的输入名完全一致(注意大小写、空格等细节)。比如如果Rive里的触发输入叫hasError,那stateMachineStatus必须等于这个字符串。
2. 正确设置输入的布尔值
你当前仅修改了stateMachineStatus变量,但并未将值传递给Rive的输入控件。需要在触发状态切换时,直接操作_input的value属性:
// 触发Error状态的方法 void _switchToError() { _input?.value = true; }
如果状态过渡是一次性触发,可根据状态机设计,在触发后重置输入值(比如延迟设置为false)。
3. 移除RiveAnimation的空controllers参数
你在RiveAnimation.asset中传入了controllers: const [],这会覆盖onInit中添加的控制器。直接移除该参数即可:
RiveAnimation.asset( 'assets/animations/sd.riv', fit: BoxFit.contain, animations: const [], onInit: _onRiveInit, ),
4. 验证状态机过渡条件配置
对照你的逻辑示意图,检查Loading到Error的过渡是否满足:
- 过渡的触发条件是否绑定了对应的布尔输入(比如当输入为true时触发)
- 过渡的触发方式是否符合需求(瞬时触发或持续触发)
修复后的完整代码示例
class RiveStateDemo extends StatefulWidget { const RiveStateDemo({super.key}); @override State<RiveStateDemo> createState() => _RiveStateDemoState(); } class _RiveStateDemoState extends State<RiveStateDemo> { SMIBool? _input; // 确保该值与Rive中的输入名称完全一致 final String stateMachineStatus = 'hasError'; void _onRiveInit(Artboard artboard) { final controller = StateMachineController.fromArtboard( artboard, 'State Machine 2', onStateChange: (stateName) { // 调试用:打印当前状态 print('当前状态:$stateName'); }, ); if (controller != null) { artboard.addController(controller); _input = controller.findInput<bool>(stateMachineStatus) as SMIBool; } } void _triggerErrorState() { // 切换到Error状态 _input?.value = true; // 若为一次性过渡,延迟重置输入值(按需调整) Future.delayed(const Duration(milliseconds: 300), () { _input?.value = false; }); } @override Widget build(BuildContext context) { return Column( children: [ RiveAnimation.asset( 'assets/animations/sd.riv', fit: BoxFit.contain, onInit: _onRiveInit, ), ElevatedButton( onPressed: _triggerErrorState, child: const Text('切换到Error状态'), ), ], ); } }
内容的提问来源于stack exchange,提问作者Alexandra Damaschin
相关产品推荐
相关产品推荐

