Search code examples
flutterflutter-layoutflutter-animation

How to animate row when children changes


How do you achieve the smooth transition when the checkmark is added?

enter image description here

Clicking the element will setState update the pressAttention variable, and therefore add the checkmark widget to the list of children of the row. For now it just instantly rebuilds the row, and adds the checkmark, but I would really like it to smoothly do as in the GIF.

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Text(
      widget.amount,
      style: const TextStyle(
          color: Colors.white, fontWeight: FontWeight.w700),
    ),
    if (pressAttention)
      Padding(
        padding: const EdgeInsets.only(left: 10),
        child: Container(
          width: 23,
          height: 23,
          decoration: BoxDecoration(
            color: Theme.of(context).highlightColor,
            shape: BoxShape.circle,
          ),
          child: Padding(
            padding: const EdgeInsets.all(4),
            child: SvgPicture.asset(
              MyIcons.checkmarkThick,
            ),
          ),
        ),
      )
  ],
),

Solution

  • try this:

    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key? key, required this.title}) : super(key: key);
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      late Animation<double> _animation;
      late Animation<double> _opacityAnimation;
      late Animation _colorAnimation;
      late AnimationController _controller;
    
      var pressAttention = false;
    
      @override
      void initState() {
        super.initState();
        _controller =
            AnimationController(duration: Duration(milliseconds: 500), vsync: this)
              ..addListener(() => setState(() {}));
        _animation = Tween(begin: 15.0, end: 0.0).animate(_controller);
        _opacityAnimation = Tween(begin: 0.0, end: 1.0).animate(_controller);
    
        _colorAnimation =
            ColorTween(begin: Colors.grey, end: Colors.purple).animate(_controller);
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.black,
          body: Center(
            child: Center(
              child: Container(
                child: InkWell(
                  splashColor: Colors.transparent,
                  highlightColor: Colors.transparent,
                  onTap: () {
                    if (pressAttention) {
                      _controller.forward();
                    } else {
                      _controller.reverse();
                    }
                    setState(() {
                      pressAttention = !pressAttention;
                    });
                  },
                  child: AnimatedBuilder(
                      animation: _controller,
                      builder: (context, child) {
                        return Container(
                          width: 100,
                          decoration: BoxDecoration(
                            border: Border.all(color: _colorAnimation.value),
                          ),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: <Widget>[
                              Transform.translate(
                                offset: Offset(_animation.value, 0),
                                child: Text(
                                  '1000',
                                  style: const TextStyle(
                                      color: Colors.white,
                                      fontWeight: FontWeight.w700),
                                ),
                              ),
                              Opacity(
                                opacity: _opacityAnimation.value,
                                child: Padding(
                                  padding: EdgeInsets.only(left: 10),
                                  child: Container(
                                    decoration: BoxDecoration(
                                      color: Theme.of(context).highlightColor,
                                      shape: BoxShape.circle,
                                    ),
                                    child: const Padding(
                                      padding: EdgeInsets.all(4),
                                      child: Icon(
                                        Icons.check,
                                        size: 13,
                                      ),
                                    ),
                                  ),
                                ),
                              )
                            ],
                          ),
                        );
                      }),
                ),
              ),
            ),
          ),
        );
      }
    }
    

    enter image description here