Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow callbacks on animation completion #95

Open
giantss opened this issue Aug 30, 2024 · 15 comments
Open

Allow callbacks on animation completion #95

giantss opened this issue Aug 30, 2024 · 15 comments

Comments

@giantss
Copy link

giantss commented Aug 30, 2024

How do I know that the animation has finished playing after calling startAnimation?

@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Aug 30, 2024

The StrokeOrderAnimationController is a ChangeNotifier and you can add listeners to it if you like. Listeners get notified whenever any part of the state changes. You should be able to do something like the following:

void listenToAnimationEnding(StrokeOrderAnimationController controller) {
  bool wasAnimating = false;

  controller.addListener(() {
    if (wasAnimating && !controller.isAnimating) {
      print('Animation ended');
    }
    wasAnimating = controller.isAnimating;
  });
}

You can use this to react to changes in any of the public attributes of the controller.

@giantss
Copy link
Author

giantss commented Sep 2, 2024

Thanks for the reply.

@giantss giantss closed this as completed Sep 2, 2024
@giantss
Copy link
Author

giantss commented Sep 2, 2024

bool wasAnimating = false;
     controller.addListener(() {
       if (wasAnimating && !controller.isAnimating) {
         controller.startQuiz();
       }
       wasAnimating = controller.isAnimating;
     });
     controller.startAnimation();

The above code implements the listener after the animation ends. But I don't know why after calling controller.startQuiz();, the listener will keep calling back until Stack Overflow appears.

image

@giantss giantss reopened this Sep 2, 2024
@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 2, 2024

Do you re-register the listener repeatedly? controller.addListener() should only be called once, for example in initState and you should dispose of it in dispose to prevent memory leaks. I can't really tell what's happening from your stack trace, but if you share the code where you register the listener, I might be able to help.

@giantss
Copy link
Author

giantss commented Sep 2, 2024

I can be sure that it is only monitored once, because I use Getx to monitor in onInit. Because 111 is only output once. But 222 will be output continuously whether it is during the stroke animation or after the stroke is completed, until Stack Overflow.

@override
  void onInit() async {
     ...
      animationController = _loadStrokeOrder(currItemData.words![0].name!);

      animationController.then((a){
        strokeOrderAnimationController = a;
        if(strokeOrderAnimationController != null){
          bool wasAnimating = false;
          Log.logs("111");
          strokeOrderAnimationController!.addListener(() {
            Log.logs("222");
            if (wasAnimating && !strokeOrderAnimationController!.isAnimating) {
              strokeOrderAnimationController!.startQuiz();
            }
            wasAnimating = strokeOrderAnimationController!.isAnimating;
          });
        }
      });
...
}

logs

I/flutter (  686): TAG:: 111 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
I/flutter (  686): TAG:: 222 :: 
....

@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 2, 2024

I think you might have some endless loop going on because you call startQuiz inside the listener and that notifies listeners again. What happens if you replace strokeOrderAnimationController!.startQuiz(); with Log.logs("333");? Do you still get the stack overflow?

@giantss
Copy link
Author

giantss commented Sep 2, 2024

Oh my god, it's really the infinite loop caused by calling strokeOrderAnimationController!.startQuiz();. But I want to start startQuiz after the animation is finished. What should I do?

@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 2, 2024

Does wasAnimating && !controller.isAnimating && !controller.isQuizzing work?

@giantss
Copy link
Author

giantss commented Sep 2, 2024

Sorry, I don't quite understand what you mean.
My requirement is to start the quiz after the autoplay animation ends.

@giantss
Copy link
Author

giantss commented Sep 2, 2024

I tried adding an extra condition && !controller.isQuizzing to the judgment condition. The Stack Overflow error no longer appears, but 222 and 333 will still be executed many times.

image image image

@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 2, 2024

Okay, so that took care of the endless loop 🥳

I am not surprised that the listener gets called multiple times. For example, the controller notifies its listeners when it switches to the next stroke.

How about you replace "222" with something more interesting, like controller.currentStroke, controller.isAnimating, and controller.isQuizzing. That should give you a better feel for when and why the listener gets triggered.

@giantss
Copy link
Author

giantss commented Sep 3, 2024

Okay, Are there plans to provide a callback method for when the animation is finished? It would be great if it were possible. Similar to onQuizCompleteCallback, it will only be triggered once under certain conditions.

@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 3, 2024

That shouldn't be too hard to add, but I don't have a timeline for it. I'll probably add it next time I need to work on this library. Feel free to open a PR though.

@Mr-Pepe Mr-Pepe changed the title How do I know that the animation has finished playing after calling startAnimation? Allow callbacks on animation completion Sep 3, 2024
@giantss
Copy link
Author

giantss commented Sep 3, 2024

Ok, thanks for your reply.

@giantss giantss closed this as completed Sep 3, 2024
@Mr-Pepe
Copy link
Collaborator

Mr-Pepe commented Sep 3, 2024

I'll keep this open as a feature request. Thank you for your feedback :)

@Mr-Pepe Mr-Pepe reopened this Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants