How to toggle rive animation when tapped on the animation in flutter

2.7k Views Asked by At

I am a beginner to rive and flutter. I am building a favorite items page in flutter. If there are not anything added to favorites I need to show a riveAnimation on screen. I already implemented almost everything to show the animation on screen. But I need to toggle a jumping animation when user tap on the animation which is really cool. for now I have the animation on 'Idle' mode

You may want to refer to the rive file => Go to Rive. And I renamed Rive stateMachine name to Bird. Everything else is the same.

summary => I want bird to jump when user tap on him :)

image

The code and the image may be little bit bigger. Sorry about that

class Favourites extends StatefulWidget {
  Favourites({Key? key}) : super(key: key);

  @override
  State<Favourites> createState() => _FavouritesState();
}

class _FavouritesState extends State<Favourites> {
  String animation = 'idle';
  SMIInput<String>? _birdInput;
  Artboard? _birdArtboard;

  void jump() {
    setState(() {
      _birdInput?.value = 'Pressed';
    });
  }

  @override
  void initState() {
    super.initState();
    rootBundle.load('assets/rive/bird.riv').then(
      (data) {
        final file = RiveFile.import(data);
        final artboard = file.mainArtboard;
        var controller = StateMachineController.fromArtboard(
          artboard,
          'Bird',
        );
        if (controller != null) {
          artboard.addController(controller);
          _birdInput = controller.findInput('Pressed');
        }
        setState(() => _birdArtboard = artboard);
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    final favourite = Provider.of<Favourite>(context);
    return Scaffold(
      backgroundColor: Colors.grey[300],
      appBar: const CustomAppBar(title: 'Favourites'),
      body: favourite.items.isEmpty
          ? Center(
              child: Column(
                children: [
                  SizedBox(
                    width: 300,
                    height: 500,
                    child: _birdArtboard == null
                        ? const SizedBox()
                        : Center(
                            child: GestureDetector(
                              onTap: () {},
                              child: Rive(artboard: _birdArtboard!),
                            ),
                          ),
                  ),
                   NeumorphicButton(),
                ],
              ),
            )
          : CustomGrid(),
    );
  }
}
1

There are 1 best solutions below

3
On BEST ANSWER

If you open/run rive file on rive site, you can find that it is using Trigger variable for jumping and it is using State Machine 1 state machine.

enter image description here

Next thing comes about declaring variable. You need to use SMITrigger data type for this and use StateMachineController to control the animation.

Use .findSMI(..) instead of .findInput() for SMITrigger.

To start animation on trigger, use

 trigger?.fire();

I will encourage you to take a look on editor and check input variable type while performing rive animation.

So the full widget that will provide animation is

class Favourites extends StatefulWidget {
  const Favourites({Key? key}) : super(key: key);

  @override
  State<Favourites> createState() => _FavouritesState();
}

class _FavouritesState extends State<Favourites> {
  String animation = 'idle';

  Artboard? _birdArtboard;
  SMITrigger? trigger;
  StateMachineController? stateMachineController;

  @override
  void initState() {
    super.initState();
    rootBundle.load('assets/rive/bird.riv').then(
      (data) {
        final file = RiveFile.import(data);
        final artboard = file.mainArtboard;
        stateMachineController =
            StateMachineController.fromArtboard(artboard, "State Machine 1");
        if (stateMachineController != null) {
          artboard.addController(stateMachineController!);
          trigger = stateMachineController!.findSMI('Pressed');

          stateMachineController!.inputs.forEach((e) {
            debugPrint(e.runtimeType.toString());
            debugPrint("name${e.name}End");
          });
          trigger = stateMachineController!.inputs.first as SMITrigger;
        }

        setState(() => _birdArtboard = artboard);
      },
    );
  }

  void jump() {
    trigger?.fire();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.grey[300],
        body: Center(
          child: Column(
            children: [
              SizedBox(
                width: 300,
                height: 400,
                child: _birdArtboard == null
                    ? const SizedBox()
                    : Center(
                        child: GestureDetector(
                          onTap: () {
                            jump();
                          },
                          child: Rive(artboard: _birdArtboard!),
                        ),
                      ),
              ),
            ],
          ),
        ));
  }
}

enter image description here