Search code examples
animationflutterflare

Is there a way to modify the initial animation state in Flare?


I've created a Flare animation which is simply a subscribe/unsubscribe button in a Flutter application.

The animation runs when the button is pressed, and all appears fine, if the user is subscribed for instance, the button reads 'subscribed' after the user pushes it. But if the user is already subscribed and returns to a relevant screen the button is not in the subscribed state. It remains in the original 'subscribe' state

I am working with a single artboard in my Flare file. It has two animations, subscribe and unsubscribe which do what they sound like. The animations do play appropriately when clicking on the button, however the states aren't preserved when a screen is reloaded. For instance if I've subscribed, and and leave the app and come back, I see the 'subscribe' button even though i've already done so.

I'm unsure if I need to have 2 separate art boards for this or if there is a better way?

class SubUnsubButton extends StatefulWidget {
  final Fight fight;
  const SubUnsubButton({
    Key key,
    @required this.fight,
  }) : super(key: key);

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

class _SubUnsubButtonState extends State<SubUnsubButton>
    with TickerProviderStateMixin {
  FlareControls flareController = FlareControls();
  String animation;

  @override
  initState() {
    super.initState();
    widget.fight.userIsSubscribed ? animation = 'Sub' : animation = 'Unsub';
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        children: <Widget>[
          Container(
            height: 50,
            child: FlatButton(
              child: FlareActor(
                "assets/animations/FightBell.flr",
                artboard: "SubUnsub",
                controller: flareController,
                fit: BoxFit.contain,
                animation: animation,
                sizeFromArtboard: true,
              ),
              onPressed: () {
                // If not subsribed
                FirebaseUser user = Provider.of<FirebaseUser>(context);
                if (!widget.fight.userIsSubscribed) {
                    animation = 'Sub';
                } else {
                    animation = 'Unsub';

                }
              },
            ),
          ),
        ],
      ),
    );
  }
}

Solution

  • You shouldn't need a second artboard. The easiest way to fix this is by adding an initState method and setting the animation value based on the same logic you have in the onPressed callback. Note that the change to the animation value in onPressed should really be done in a setState call to ensure the widget is updated when the animation value changes.

    A generally cleaner way to do this is using a boolean value like isSubscribed instead of encapsulating the isSubscribed logic into another (Fight) object. This will allow the flutter widget system to automatically call didUpdateWidget on your State class when isSubscribed changes. Then you can respond to that change by doing calling setState and changing the animation value. You'd probably pass in some other callback to be invoked when onPressed is called so that the widget using this SubUnsubButton can change the isSubscribed value.

    You may not need a stateful widget at all, take a look at the checkbox example in the Flare-Flutter repository. It displays a list of checkboxes with randomly chosen values at boot for whether they are checked or not. The SmileySwitch checkbox class is implemented as a stateless widget while the implementing Settings class just iterates through the values, creates a SmileySwitch for each, and then responds to the onToggle callback by changing the value as necessary. This should be pretty similar to what you are trying to do.