Воспроизведение той же анимации вспышки в Flutter

#flutter #flutter-layout #flutter-animation #flare

#flutter #flutter-layout #flutter-анимация #вспышка

Вопрос:

Я пытаюсь повторно воспроизвести анимацию вспышки во Flutter. Не зацикливайте анимацию, когда она завершена. Я хочу, чтобы анимация воспроизводилась по запросу, та же анимация.

Когда я переключаюсь между анимациями, это работает нормально, просто меняя строку местами и вызывая 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
  

Все вызывается, оно воспроизводится в первый раз, но после этого анимация не воспроизводится.

Ответ №1:

Более чистый способ сделать это — использовать пользовательский FlareController. Существует конкретная реализация FlareControls, которая хорошо подходит для этого варианта использования.

 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),
      ),
    );
  }
}
  

Обратите внимание, что в этом примере также воспроизводится фоновая анимация в режиме ожидания, которая зацикливается. Любой вызов FlareControls.воспроизведение смешает входящую анимацию с этой фоновой анимацией ожидания. Вы просто опускаете аргумент animation: «idle», если вы не хотите / нуждаетесь в фоновой анимации.

Полный пример здесь:https://github.com/luigi-rosso/flare_controls

Комментарии:

1. Оооооооо, это выглядит намного лучше. По какой-то причине я не смог найти ничего подобного. Позвольте мне реализовать это таким образом и посмотреть, работает ли это. Я вернусь к вам через некоторое время.

2. это намного лучшее решение, чем мое. Спасибо.

Ответ №2:

Основываясь на ответе от @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 за посев семян.

Комментарии:

1. большой палец вверх за использование таймера. Я хотел прекратить воспроизведение анимации через 1 секунду. Помог таймер.

Ответ №3:

  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;

                         });
                       }
                      },
                    )