Search code examples
flutteranimationflutter-layoutflutter-animation

show animation on button click flutter


I have a column of buttons on my app. The middle button needs to be animated. So basically when the user taps I need to show an animation.

enter image description here

As you can see the heart button has two parts. Anything below the heart button is fixed. Anything above the heart button is animated. So the 9 should only be visible when the actual button is tapped.

This is my code for reaction_button so far:

        Column(
          children: [
            AnimatedOpacity(
              opacity: isVisible ? 1.0 : 0.0,
              duration: const Duration(seconds: 1),
              child: AnimatedContainer(
                duration: const Duration(seconds: 1),
                curve: Curves.bounceInOut,
                child: CounterCard(count: userLikeCount),
              ),
            ),
            LikeButton(
              size: 40,
              animationDuration: const Duration(milliseconds: 500),
              likeCountAnimationDuration: const Duration(milliseconds: 10),
              bubblesColor: const BubblesColor(
                dotPrimaryColor: Colors.red,
                dotSecondaryColor: Colors.red,
              ),
              circleColor: const CircleColor(
                start: Colors.pink,
                end: Colors.pink,
              ),
              likeBuilder: (isLiked) {
                return SvgPicture.asset(
                  "assets/icons/heart.svg",
                  color: buttonColor,
                );
              },
              onTap: (isLiked) => increment(isLiked),
            ),
            Text(
              likeCount.toString(),
              style: const TextStyle(
                fontWeight: FontWeight.w400,
                color: Colors.black,
              ),
            )
          ],
        ),
  Future<bool> increment(bool isLiked) async {
    setState(() {
      likeCount++;
      userLikeCount++;
      buttonColor = Colors.pink;
    });
    if (userLikeCount >= 100) {
      userLikeCount = 100;
    }
    setState(() {
      isVisible = true;
    });
    Future.delayed(const Duration(milliseconds: 800)).then((value) {
      setState(() {
        isVisible = false;
      });
    });
    return true;
  }

For now when the user presses the button a simple CountCard is shown which disappears after 1 second. What I need to add is an up going(I dont know the word for it, FadeUp animation?). I made the disappearing part work.

thanks to @yeasin_sheikh this is what I have managed so far:

  AnimatedContainer(
     transform: animation.value,
     color: Colors.red,
     duration: controller.duration!,
     child: Visibility(
        visible: isVisible,
        child: CounterCard(count: userLikeCount),
     ),
   ),

for on tap

    controller.forward();
    setState(() {
      isVisible = true;
    });
    Future.delayed(const Duration(seconds: 1)).then((value) {
      controller.reverse();
      setState(() {
        isVisible = false;
      });
    });

and initialized:

  late final controller = AnimationController(
      vsync: this, duration: const Duration(milliseconds: 200))
    ..addListener(() {
      setState(() {});
    });
  late final animation = Tween<Matrix4>(
          begin: Matrix4.translationValues(0, 30, 0), end: Matrix4.identity())
      .animate(controller);

The result is as:

Result

All the buttons are moving which I don't like much and if the user presses the react button quickly the animation gets all fuzzy. So, any suggestions regarding those are highly appreciated.


Solution

  • You can check this widget for basic animation, better might be using AnimationBuilder.

    class TAn extends StatefulWidget {
      const TAn({super.key});
    
      @override
      State<TAn> createState() => _TAnState();
    }
    
    class _TAnState extends State<TAn> with SingleTickerProviderStateMixin {
      late final controller =
          AnimationController(vsync: this, duration: Duration(milliseconds: 200))
            ..addListener(() {
              setState(() {});
            });
    // I was curious if Matrix4 will work or not 😅
      late final animation = Tween<Matrix4>(
              begin: Matrix4.translationValues(0, 48, 0), end: Matrix4.identity())
          .animate(controller);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                AnimatedContainer(
                  transform: animation.value,
                  color: Colors.red,
                  duration: controller.duration!,
                  child: Text("6."),
                ),
                ElevatedButton(
                  onPressed: () {
                    controller.forward();
                  },
                  child: Text("show "),
                ),
                ElevatedButton(
                  onPressed: () {
                    controller.reverse();
                  },
                  child: Text(" hide"),
                )
              ],
            ),
          ),
        );
      }
    }