4

I have a problem with the animation, I want the heart to start small, increase and then decrease in size, as shown in the gif below.

Desired animation

enter image description here

But the current behavior is that the heart starts out big and then slows down.

enter image description here

Would anyone know what it would take to fix the animation?

Here is the flutter code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage();

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  Animation<double> _heartAnimation;
  AnimationController _heartController;

  @override
  void dispose() {
    _heartController.dispose();
    super.dispose();
  }

  void _animate() {
    _heartController
      ..reset()
      ..forward(from: 0.0)
      ..reverse(from: 1.0);
  }

  @override
  void initState() {
    super.initState();
    final quick = const Duration(milliseconds: 500);
    final scaleTween = Tween(begin: 0.0, end: 1.0);
    _heartController = AnimationController(duration: quick, vsync: this);
    _heartAnimation = scaleTween.animate(
      CurvedAnimation(
        parent: _heartController,
        curve: Curves.elasticOut,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ScaleTransition(
          scale: _heartAnimation,
          child: Icon(Icons.favorite, size: 160.0, color: Colors.red),
        )
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _animate();
        },
        child: Icon(Icons.favorite_rounded),
      ),
    );
  }
}

2 Answers 2

6

Try this code, it works for me perfectly. If you have any questions please let know.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: MyHomePage());
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage();

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    final quick = const Duration(milliseconds: 500);
    final scaleTween = Tween(begin: 0.0, end: 1.0);
    controller = AnimationController(duration: quick, vsync: this);
    animation = scaleTween.animate(
      CurvedAnimation(
        parent: controller,
        curve: Curves.fastLinearToSlowEaseIn,
      ),
    )..addListener(() {
      setState(() => scale = animation.value);
    });
      
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  void _animate() {
    animation
    ..addStatusListener((AnimationStatus status) {
      if (scale == 1.0) {
        controller.reverse();
      } 
    });
    controller.forward();
  }

  double scale = 0.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Transform.scale(
          scale: scale,
          child: Icon(
            Icons.favorite,
            size: 160.0,
            color: Colors.red
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _animate();
        },
        child: Icon(Icons.favorite_rounded),
      )
    );
  }
}
0
0

You can achieve the desired animation using the zoom-in effect, we can learn it through the Flutter doc, or refer to the code below:

class _ManageScale extends State<YourClass> with TickerProviderStateMixin{

late final AnimationController controller = AnimationController(
 duration: const Duration(seconds:2),    
vsync: this,
)..repeat(reverse:true) ;
late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
curve:Curve.fastOutSlowIn,  
);

 Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ScaleTransition(
          scale: _animation,
          child: const Padding(
            padding: EdgeInsets.all(8.0),
            child: <Place_Your_Heart_Shape>(size: 150.0),
          ),
        ),
      ),
    );
  }
`


class _ManageScale extends State<YourClass> with TickerProviderStateMixin{

late final AnimationController controller = AnimationController(
 duration: const Duration(seconds:2),    
vsync: this,
)..repeat(reverse:true) ;//putting repeat reverse true is make your container big and small in same order

late final Animation<double> _animation = CurvedAnimation(
parent: _controller,
curve:Curve.fastOutSlowIn,  
);

//for proper implementation of above stateful widget see doc

now use above animation as a property in your widget which is _animation

 Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ScaleTransition(
          scale: _animation,
          child: const Padding(
            padding: EdgeInsets.all(8.0),
            child: <Place_Your_Heart_Shape>(size: 150.0),
          ),
        ),
      ),
    );
  }

Not the answer you're looking for? Browse other questions tagged or ask your own question.