Flutter - How to enable AnimatedOpacity automatically?

Viewed 16377

I'm creating a dashboard which contain Tween animation for two widgets, Text and two Container. But, I want to make the two Container's opacity changing slowly from invisible to visible...so I used AnimatedOpacity. But I don't know how to do it...

Any help would be appreciated..

class _IntroState extends State<Intro> with SingleTickerProviderStateMixin {
  Animation animation;
  AnimationController animationController;

   @override
   void initState() {
     super.initState();
      animationController = AnimationController(
        duration: Duration(seconds: 2),
        vsync: this,
     );

    animation = Tween(begin: -1.0, end: 0.0).animate(CurvedAnimation(
        parent: animationController, curve: Curves.fastOutSlowIn));
    animationController.forward();
  }

  @override
  Widget build(BuildContext context) {
    bool _visible = false;
    final double width = MediaQuery.of(context).size.width;

  return AnimatedBuilder(
      animation: animationController,
      builder: (BuildContext context, Widget child) {
         return Scaffold(
           //BODDY
            body: ListView(
              hildren:<Widget>[
                 new Stack(
                   children: <Widget>[
                     new Transform(
                       //ANIMATED OPACITY
                       new AnimatedOpacity(
                          opacity: _visible ? 0.0 : 1.0,
                          duration: Duration(milliseconds: 500),
                          child: new Padding(
                            padding: const EdgeInsets.symmetric(
                                  horizontal: 12.0),
                            child: new Row(
                               children: <Widget>[
                                  Expanded(
                                   child: Row(
                                     children: <Widget>[
                                       child: Padding(
                                         padding: const EdgeInsets.symmetric(horizontal: 8.0),
                                          child: Container(
                                            child: Column(
                                              children: <Widget>[
                                                //THIS THE CONTAINER
                                                new Container(. . .),
                                                new Container(. . .)
4 Answers

Instead of AnimatedOpacity, use a FadeTransition widget. This gives you manual control over the animation:

  @override
  Widget build(BuildContext context) {
    return FadeTransition(
      opacity: animationController.drive(CurveTween(curve: Curves.easeOut)),
      child: ...,
    );
  }

To make a StatelessWidget or StatefulWidget fade in automatically on creation, TweenAnimationBuilder provides an even easier solution:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TweenAnimationBuilder<double>(
        tween: Tween<double>(begin: 0.0, end: 1.0),
        curve: Curves.ease,
        duration: const Duration(seconds: 1),
        builder: (BuildContext context, double opacity, Widget? child) {
          return Opacity(
              opacity: opacity,
              child: Container(width: 20, height: 20, color: Colors.red)
          );
    });
  }
}

See my Codepen for a complete example: https://codepen.io/atok/pen/BaZVRPr

Best regards

For anyone who'd like to fade a widget automatically as soon as the page is rendered and still wants to use AnimatedOpacity, you can put the call to change the state of the opacity in the WidgetsBinding's addPostFrameCallback callback.

Put this code below in your initState.

WidgetsBinding.instance.addPostFrameCallback((_) {
    setState(() {
        _opacity = 1;
    });
});

I totally recommend using @boformer 's answer above.

But, I played around with your code and wanted to show you how you can call setState to trigger the AnimatedOpacity, so you can see that it is working without onTap or GestureDetector as you were thinking in the comments above.

I got your code and played around with it. What I did is, simply added a status listener to your animation controller and when the controller is done. I triggered the visibility boolean in setState. Then it will change the visibility of the containers.

// When animation finished change the visibility.
animationController.addStatusListener((status){
  if (status == AnimationStatus.completed) {
    setState(() {
      // This is opposite, because it's implemented opposite in your code.
      _visible = false;
    });
  }
});
Related