rive-flutter icon indicating copy to clipboard operation
rive-flutter copied to clipboard

The play-pause animation example does not work

Open arungopalan opened this issue 3 years ago • 1 comments

https://github.com/rive-app/rive-flutter/blob/master/example/lib/play_pause_animation.dart

It keeps resetting the _controller.isActive to true and the animation never pauses.

arungopalan avatar Oct 18 '22 17:10 arungopalan

Okay I have managed to fix the issue. Basically create the riveAnimation in the initState and reuse the reference instead of recreating inside the build.

Can someone with a write access to the repository please update the play_pause_animation.dart file with the contents below.

/// Demonstrates how to play and pause a looping animation

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

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

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

class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
  /// Controller for playback
  late RiveAnimationController _controller;

  /// Toggles between play and pause animation states
  void _togglePlay() =>
      setState(() => _controller.isActive = !_controller.isActive);

  /// Tracks if the animation is playing by whether controller is running
  bool get isPlaying => _controller.isActive;

  late RiveAnimation _riveAnimation;

  @override
  void initState() {
    super.initState();
    _controller = SimpleAnimation('idle');
    _riveAnimation = RiveAnimation.network(
      'https://cdn.rive.app/animations/vehicles.riv',
      controllers: [_controller],
      // Update the play state when the widget's initialized
      onInit: (_) => setState(() => {print("On init called")}),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Animation Example'),
      ),
      body: Center(
        child: _riveAnimation,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _togglePlay,
        tooltip: isPlaying ? 'Pause' : 'Play',
        child: Icon(
          isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

arungopalan avatar Oct 19 '22 00:10 arungopalan

Hi @arungopalan thank you for taking the time to look into this. Not sure what the cause was for this. We did have a bug in v0.10.0 that resulted in the play/pause example not working.

The default example should work now in the latest version 0.10.1

/// Demonstrates how to play and pause a looping animation

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

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

  @override
  State<PlayPauseAnimation> createState() => _PlayPauseAnimationState();
}

class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
  /// Controller for playback
  late RiveAnimationController _controller;

  /// Toggles between play and pause animation states
  void _togglePlay() =>
      setState(() => _controller.isActive = !_controller.isActive);

  /// Tracks if the animation is playing by whether controller is running
  bool get isPlaying => _controller.isActive;

  @override
  void initState() {
    super.initState();
    _controller = SimpleAnimation('idle');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Animation Example'),
      ),
      body: RiveAnimation.asset(
        'assets/off_road_car.riv',
        fit: BoxFit.cover,
        controllers: [_controller],
        // Update the play state when the widget's initialized
        onInit: (_) => setState(() {}),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _togglePlay,
        tooltip: isPlaying ? 'Pause' : 'Play',
        child: Icon(
          isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

Note: the setState call is only needed to update the UI (not to update the rive animation)

Closing this for now, please feel free to reopen if the above does not work for you on the latest version.

HayesGordon avatar Jan 17 '23 11:01 HayesGordon

Hey @HayesGordon, the above example doesn't seem to work can you please have a look, I am using the latest version rive: ^0.11.4. The animation cannot be controlled with the controller.

Rive Asset: dark.zip

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';

void main() {
  runApp(const MyApp());
}

class AppScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter App',
      scrollBehavior: AppScrollBehavior(),
      theme: ThemeData(
        colorSchemeSeed: Colors.indigo,
        useMaterial3: true,
        brightness: Brightness.light,
      ),
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
        brightness: Brightness.dark,
      ),
      home: PlayPauseAnimation(),
      debugShowCheckedModeBanner: false,
    );
  }
}

/// Demonstrates how to play and pause a looping animation

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

  @override
  State<PlayPauseAnimation> createState() => _PlayPauseAnimationState();
}

class _PlayPauseAnimationState extends State<PlayPauseAnimation> {
  /// Controller for playback
  late RiveAnimationController _controller;

  /// Toggles between play and pause animation states
  void _togglePlay() =>
      setState(() => _controller.isActive = !_controller.isActive);

  /// Tracks if the animation is playing by whether controller is running
  bool get isPlaying => _controller.isActive;

  @override
  void initState() {
    super.initState();
    _controller = SimpleAnimation('idle');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Animation Example'),
      ),
      body: RiveAnimation.asset(
        'assets/rive/dark.riv',
        fit: BoxFit.cover,
        controllers: [_controller],
        // Update the play state when the widget's initialized
        onInit: (_) => setState(() {}),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _togglePlay,
        tooltip: isPlaying ? 'Pause' : 'Play',
        child: Icon(
          isPlaying ? Icons.pause : Icons.play_arrow,
        ),
      ),
    );
  }
}

maheshj01 avatar Jul 18 '23 17:07 maheshj01

My Bad looks like I passed in the wrong Animation name to the controller.

 _controller = SimpleAnimation('idle'); // should be "orbitAnimation"

maheshj01 avatar Jul 18 '23 17:07 maheshj01