Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't my Flutter animated checkmark working?

I'm trying to replicate the following animation from dribble.com:

I've gotten the ScaleTransition to work but the SizeTransition does not. What am I doing wrong or what don't I understand?

When I only swap out the SizeTransition with a FadeTransition (and keep the same controllers & animations), the animations both run. When I move the Center widget from being a child of the SizeTransition to the parent the animation runs. However it is not properly centered.

import 'package:flutter/material.dart';

class AnimatedCheck extends StatefulWidget {
  @override
  _AnimatedCheckState createState() => _AnimatedCheckState();
}

class _AnimatedCheckState extends State<AnimatedCheck> with TickerProviderStateMixin {
  late AnimationController scaleController = AnimationController(duration: const Duration(milliseconds: 800), vsync: this);
  late Animation<double> scaleAnimation = CurvedAnimation(parent: scaleController, curve: Curves.elasticOut);
  late AnimationController checkController = AnimationController(duration: const Duration(milliseconds: 400), vsync: this);
  late Animation<double> checkAnimation = CurvedAnimation(parent: checkController, curve: Curves.linear);

  @override
  void initState() {
    super.initState();
    scaleController.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        checkController.forward();
      }
    });
    scaleController.forward();
  }

  @override
  void dispose() {
    scaleController.dispose();
    checkController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    double circleSize = 140;
    double iconSize = 108;

    return ScaleTransition(
      scale: scaleAnimation,
      child: Container(
        height: circleSize,
        width: circleSize,
        decoration: BoxDecoration(
          color: Colors.green,
          shape: BoxShape.circle,
        ),
        child: SizeTransition(
          sizeFactor: checkAnimation,
          axis: Axis.horizontal,
          axisAlignment: -1,
          child: Center(
            child: Icon(Icons.check, color: Colors.white, size: iconSize)
          )
        ),
      ),
    );
  }
}
like image 527
StaticReturn Avatar asked Dec 21 '25 15:12

StaticReturn


2 Answers

When you move the Center to the outside, it doesn't center the children of it's children, just puts it's child in the center of the area it occupies. Try setting the Container alignment using alignment: Alignment.center, inside of the Container. Please let me know if it doesn't work and I'll replicate the code to figure out the problem is.

Edit: This is because there is space around the visual check you see, the SizeTransition doesn't know this so it animates from the edge of the Icon which causes the visual bug you see. I'd recommend you use a tool like Rive (rive.app) to accomplish what you want, alternatively, you can use another animation or use some clunky workaround like animating the position while the size transition occurs so that it appears to be centered.

Hi if this is an issue for you, I figured out how both animations will be triggerd. See code below.

Stack(
    children: [
      Center(
        child: ScaleTransition(
          scale: scaleAnimation,
          child: Container(
            height: circleSize,
            width: circleSize,
            decoration: BoxDecoration(
              color: kApprovedColor,
              shape: BoxShape.circle,
            ),
          ),
        ),
      ),
      SizeTransition(
        sizeFactor: checkAnimation,
        axis: Axis.horizontal,
        axisAlignment: -1,
        child: Center(
          child: Icon(Icons.check, color: Colors.white, size: iconSize),
        ),
      ),
    ],
  ),
like image 24
M. Kaiser Avatar answered Dec 24 '25 04:12

M. Kaiser



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!