5

Passing state down to widgets is easy. I have a StatefulWidget that contains an animation with its controller. I need to be able to trigger the animation from another widget higher in my widget tree.

app

My MainApp should trigger the animation using a button.

enter image description here

As I understand AnimationController only has an imperative API. I can call controller.forward() or controller.reverse(). But to do this I need to expose the controller to my MainApp.

What I currently do is to keep a global variable of my state around.

class MainApp extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( ... body: new LogoWidget(), ); } _startAnimation() { _state.restartAnimation(); } } _LogoWidgetState _state; // yuk! class LogoWidget extends StatefulWidget { _LogoWidgetState createState() { _state = _LogoWidgetState(); return _state; } } class _LogoWidgetState extends State<LogoWidget> with SingleTickerProviderStateMixin { Animation<double> animation; AnimationController controller; restartAnimation() { controller.value == 1.0 ? controller.reverse() : controller.forward(); } ... } 

(full sourcecode here)

What is a better way to deal with this?

2
  • Why does LogoWidget holds animation stuff if it's supposed to be controlled somewhere else ? Commented May 11, 2018 at 14:51
  • well...the animation-widget itself should just react to the app state...otherwise I'd have to pull out the AnimationController but the MainApp should not care about that at all. Commented May 11, 2018 at 15:24

1 Answer 1

1

You don't need _LogoWidgetState _state; // yuk! out in the middle of nowhere, but you can try:

  1. create LogoWidget _myBody = LogoWidget(), and use that for your body:
  2. similarily, apply with final _LogoWidgetState _state = _LogoWidgetState()
  3. then call it as _myBody._state.restartAnimation()

Your sample, modified:

class MainApp extends StatelessWidget { LogoWidget _myBody = LogoWidget(); //<--- @override Widget build(BuildContext context) { return new Scaffold( ... body: _myBody, //<--- ); } _startAnimation() { _myBody._state.restartAnimation(); //<--- } } class LogoWidget extends StatefulWidget { final _LogoWidgetState _state = _LogoWidgetState(); //<--- _LogoWidgetState createState() { return _state; } } 

But if you think _myBody._state.restartAnimation() is too long, you can shorten it with:

class LogoWidget extends StatefulWidget { final _LogoWidgetState _state = _LogoWidgetState(); //<--- void restartAnimation() { //<--- _state.restartAnimation(); } _LogoWidgetState createState() { return _state; } } 

Then just use _myBody.restartAnimation()

Here's some relevant posts:

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.