Why isn't my Flutter animated checkmark working?

1,241

Solution 1

Flutter's documentation has an explanation:

Like most widgets, SizeTransition will conform to the constraints it is given, so be sure to put it in a context where it can change size. For instance, if you place it into a Container with a fixed size, then the SizeTransition will not be able to change size, and will appear to do nothing.

Thank you. Now I know what I'm doing wrong.

Solution 2

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),
        ),
      ),
    ],
  ),

Solution 3

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.

Share:
1,241
StaticReturn
Author by

StaticReturn

Updated on December 29, 2022

Comments

  • StaticReturn
    StaticReturn over 1 year

    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)
              )
            ),
          ),
        );
      }
    }
    
  • StaticReturn
    StaticReturn almost 3 years
    When I add an "alignment: Alignment.center" to the Container, the checkmark goes through a SizeTransition & slides from the right side of the screen to the center. (very not cool). When I remove the Center on the Icon and then add the "alignment: Alignment.center", it goes through a SizeTransition & slides from the right side of the circle to the center. (better, but still not right). At least the SizeTransition animates now?
  • Hady
    Hady almost 3 years
    @StaticReturn Alright, I'll try out your code, find a fix and update my answer.
  • Hady
    Hady almost 3 years
    @StaticReturn After recreating your code, everything is working as it should. The problem is a visual one, the cause is that there is space around the Icon caused by the Center inside of the icon (see this: cln.sh/asDfIl). The Center widget takes up the entire space of the container then puts it's child. The SizeTransition animates the Center and not the icon. Removing the center or putting it above the size transition will cause the icon to not be Centered and the same problem happens anyways because the icon doesn't take up it's full size. I'd recommend you do this with a tool like