2

我正在尝试在 Flutter 中重新播放 Flare 动画。动画完成后不循环播放。我想要一个动画按需播放,相同的动画。

当我在动画之间切换时,只需交换字符串并调用 setState 就可以正常工作。有没有一种简单的方法可以做到这一点。

这是我目前正在做的事情。

class _FlareDemoState extends State<FlareDemo> {

  String animationToPlay = 'activate';

  @override
  Widget build(BuildContext context) {

    print('Animation to play: $animationToPlay');

    return Scaffold(
      backgroundColor: Colors.purple,
      body: GestureDetector(
        onTap: () {
          setState(() {

          });
        },
        child: FlareActor('assets/button-animation.flr',
            animation: animationToPlay)));
   }
}

当我点击动画时,我的日志结果

I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
I/chatty  (18959): uid=10088(com.example.flare_tutorial) Thread-2 identical 2 lines
I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
I/chatty  (18959): uid=10088(com.example.flare_tutorial) Thread-2 identical 7 lines
I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
Reloaded 2 of 495 libraries in 672ms.
I/flutter (18959): Animation to play: activate

一切都被调用,它第一次播放,但之后动画不会重播。

4

3 回答 3

6

A cleaner way to do this is using a custom FlareController. There's a concrete FlareControls implementation that fits this use case nicely.

class _MyHomePageState extends State<MyHomePage> {
  // Store a reference to some controls for the Flare widget
  final FlareControls controls = FlareControls();

  void _playSuccessAnimation() {
    // Use the controls to trigger an animation.
    controls.play("success");
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: FlareActor("assets/Teddy.flr",
          animation: "idle",
          fit: BoxFit.contain,
          alignment: Alignment.center,
          // Make sure you use the controls with the Flare Actor widget.
          controller: controls),
      floatingActionButton: FloatingActionButton(
        onPressed: _playSuccessAnimation,
        tooltip: 'Play',
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

Note that this example also plays an idle background animation which loops. Any call to FlareControls.play will mix the incoming animation over this background idle animation. You simply omit the animation: "idle" argument if you don't want/need a background animation.

完整示例:https ://github.com/luigi-rosso/flare_controls

于 2019-03-22T18:53:56.413 回答
1

根据@Eugene 的回答,我想出了一个临时解决方案。我将值设置为空,启动一个 50 毫秒的计时器,然后将值设置回我想再次播放的动画。

class _FlareDemoState extends State<FlareDemo> {

String animationToPlay = 'activate';

@override
Widget build(BuildContext context) {

print('Animation to play: $animationToPlay');

return Scaffold(
  backgroundColor: Colors.purple,
  body: GestureDetector(
    onTap: () {
      _setAnimationToPlay('activate');
    },
    child: FlareActor('assets/button-animation.flr',
        animation: animationToPlay)));
  }
}

void _setAnimationToPlay(String animation) {
  if (animation == _animationToPlay) {
    _animationToPlay = '';
    Timer(const Duration(milliseconds: 50), () {
      setState(() {
        _animationToPlay = animation;
      });
    });
  } else {
    _animationToPlay = animation;
  }
}

这是一个混乱的解决方法,但它可以完成工作。感谢@Eugene 播种。

于 2019-03-22T16:38:13.183 回答
-1
 FlareActor(
                      "assets/animation/day_night.flr",
                      alignment: Alignment.center,
                      fit: BoxFit.cover,
                      animation: _animation,
                      callback: (string) {
                       if(string=="switch_night"){
                         setState(() {
                           _animation = _animationNight;

                         });
                       }else if(string=="switch_day"){
                         setState(() {
                           _animation = _animationDay;

                         });
                       }
                      },
                    )
于 2020-02-28T13:05:34.087 回答