You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter骰子应用首次点击无Rive动画,后续正常问题求助

解决Flutter Rive骰子动画首次点击不触发问题

问题分析

首次点击按钮时动画无响应,第二次及之后正常,核心原因:

  1. 旧版RiveFile.initialize()调用导致初始化延迟,状态机未完全就绪时触发动画无效;
  2. 首次点击时骰子数值更新与动画触发的时序冲突,状态机未及时接收数值变化就触发了trigger。

解决方案

1. 移除废弃初始化代码

新版rive库已自动完成初始化,无需手动调用RiveFile.initialize(),删除该行可避免初始化流程异常。

2. 优化动画触发时序

通过addPostFrameCallback等待当前帧绘制完成后再触发动画,确保骰子数值已同步到Rive状态机。

3. 完善初始化状态控制

初始化时设置骰子默认值,同时给按钮添加状态判断,避免未就绪时的无效点击。

修改后的完整代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rive/rive.dart';

class Rolldice extends StatefulWidget {
  const Rolldice({super.key});

  @override
  State<Rolldice> createState() => _RolldiceState();
}

class _RolldiceState extends State<Rolldice> {
  Artboard? riveArtboard;
  var dicevalue = 1; // 初始化默认点数
  SMINumber? diceNumber;
  SMITrigger? rollTrigger;
  bool isRolling = false;

  @override
  void initState() {
    _loadRiveFile();
    super.initState();
  }

  void _loadRiveFile() async {
    try {
      final data = await rootBundle.load("assets/images/shakeable_dice.riv");
      final file = RiveFile.import(data);
      final artboard = file.mainArtboard;

      final controller = StateMachineController.fromArtboard(artboard, 'StateIdle');
      if (controller != null) {
        artboard.addController(controller);

        diceNumber = controller.findSMI('Number');
        rollTrigger = controller.findSMI('Trigger');

        // 同步初始数值到状态机
        if (diceNumber != null) {
          diceNumber!.value = dicevalue.toDouble();
        }

        setState(() => riveArtboard = artboard);
      }
    } catch (e) {
      print("Error loading Rive file: $e");
    }
  }

  void _triggerRoll() {
    if (isRolling) return;
    isRolling = true;

    final newDiceValue = Random().nextInt(6) + 1;
    setState(() {
      dicevalue = newDiceValue;
    });

    diceNumber!.value = newDiceValue.toDouble();

    // 等待帧绘制完成后触发动画,确保数值同步完成
    WidgetsBinding.instance.addPostFrameCallback((_) {
      rollTrigger!.fire();
    });

    Future.delayed(const Duration(seconds: 1), () {
      setState(() {
        isRolling = false;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Roll Dice')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Expanded(
              child: riveArtboard == null
                  ? const Center(child: Text("Loading..."))
                  : Center(child: Rive(artboard: riveArtboard!)),
            ),
            const SizedBox(height: 20),
            Text(
              dicevalue.toString(),
              style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: (rollTrigger == null || isRolling) ? null : _triggerRoll,
              child: Text(isRolling ? "Rolling..." : "Roll"),
            ),
          ],
        ),
      ),
    );
  }
}

额外检查项

确保你的Rive文件状态机配置正确:

  • StateIdle状态机中,Trigger输入需正确关联「Idle → Rolling」的过渡条件;
  • Number输入需绑定到骰子点数的显示逻辑,动画结束后会根据该数值切换到对应点数状态。

内容的提问来源于stack exchange,提问作者Yongsak Saengsuk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:43:16