How to use rive's state machine in flutter?

Issue

I’ve created a .riv file with 3 state animations: start, processing, end, which are in "State machine". Rive team recently announced a new feature with dinamically changing animations, it’s "State machine". Not sure, how to use it in flutter project, i.e how to dynamically change value of animation. If somebody needs some code, no problem, I could provide. Moreover, link to rive’s "state machine" https://www.youtube.com/watch?v=0ihqZANziCk. I didn’t find any examples related to this new feature. Please help! Thanks.

Solution

There are examples on rives pub package site. Here is one for state machine.
example_state_machine.dart

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

/// An example showing how to drive two boolean state machine inputs.
class ExampleStateMachine extends StatefulWidget {
  const ExampleStateMachine({Key? key}) : super(key: key);

  @override
  _ExampleStateMachineState createState() => _ExampleStateMachineState();
}

class _ExampleStateMachineState extends State<ExampleStateMachine> {
  /// Tracks if the animation is playing by whether controller is running.
  bool get isPlaying => _controller?.isActive ?? false;

  Artboard? _riveArtboard;
  StateMachineController? _controller;
  SMIInput<bool>? _hoverInput;
  SMIInput<bool>? _pressInput;

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

    // Load the animation file from the bundle, note that you could also
    // download this. The RiveFile just expects a list of bytes.
    rootBundle.load('assets/rocket.riv').then(
      (data) async {
        // Load the RiveFile from the binary data.
        final file = RiveFile.import(data);

        // The artboard is the root of the animation and gets drawn in the
        // Rive widget.
        final artboard = file.mainArtboard;
        var controller =
            StateMachineController.fromArtboard(artboard, 'Button');
        if (controller != null) {
          artboard.addController(controller);
          _hoverInput = controller.findInput('Hover');
          _pressInput = controller.findInput('Press');
        }
        setState(() => _riveArtboard = artboard);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey,
      appBar: AppBar(
        title: const Text('Button State Machine'),
      ),
      body: Center(
        child: _riveArtboard == null
            ? const SizedBox()
            : MouseRegion(
                onEnter: (_) => _hoverInput?.value = true,
                onExit: (_) => _hoverInput?.value = false,
                child: GestureDetector(
                  onTapDown: (_) => _pressInput?.value = true,
                  onTapCancel: () => _pressInput?.value = false,
                  onTapUp: (_) => _pressInput?.value = false,
                  child: SizedBox(
                    width: 250,
                    height: 250,
                    child: Rive(
                      artboard: _riveArtboard!,
                    ),
                  ),
                ),
              ),
      ),
    );
  }
}

Answered By – Nicolas Morawietz

Answer Checked By – Katrina (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published.