Search code examples
flutterflutter-animationflutter-provider

Flutter laggy animation


my animation seems to be lagging a bit and I'm not sure why...

I have a parent widget - Stack which also uses a Provider to share the screen's state. Depending on the state (basically an enum) the child widgets (Child1, Child2, Child3) change their position (AnimatedPositioned) within the stack...

It is important to say that the state is changed from the children (it's not using setState, provider is taking care of that). Each child has a button that when pressed changes the state. Like this:

  void onPressChangeState(State state) {
    state.state = AnotherState;
  }

Parent Widget:

class Parent extends StatefulWidget {
  @override
  _ParentState createState() => _ParentState();
}

class _ParentState extends State<Parent> {
  State state = State();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: ChangeNotifierProvider(
        create: (_) => state,
        child: Stack(
          // Each of the children takes care of its animation.
          children: [
            Child1(),
            Child2(),
            Child3(),
          ],
        ),
      ),
    );
  }
}

Child(s) Widget (they follow the same structure). Note that the children widgets use both AnimatedPositioned (so that they move around depending on the state) and AnimatedOpacity (so that the opacity changes with the state).

class SignUpSheet extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var media = MediaQuery.of(context);
    var width = media.size.width;
    var height = media.size.height * Sheet.heightRatio - media.padding.top;

    double yOffset;
    double xOffset;
    double opacity;

    var state = Provider.of<State>(context);
    switch (state.state) {
      case State1:
        yOffset = height;
        xOffset = 0;
        opacity = 1;
        break;
      case State2:
        yOffset = 0 - media.viewInsets.bottom;
        xOffset = 0;
        opacity = 1;
        break;
      case State3:
        height += 25;
        yOffset = 0 - media.viewInsets.bottom;
        xOffset = 10;
        opacity = 0.4;
        break;
    }

    return AnimatedPositioned(
      width: width,
      height: height,
      duration: Duration(milliseconds: 1000),
      curve: Curves.fastLinearToSlowEaseIn,
      bottom: -offset,
      child: AnimatedOpacity(
         opacity: opacity,
         duration: Duration(milliseconds: 1000),
         curve: Curves.fastLinearToSlowEaseIn,
         child: Column(...),
    );
  }
}

I think my issue has something to do with that the children widgets are stateless and rebuild too much. The lag is not that much but it is noticeable.


Solution

  • I built the app using profiling mode and the animation is a lot smoother. I saw in an optimization talk that we should not assess animations based on debug mode and instead use profiling.