You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter心形缩放动画异常修复咨询:实现从小到大再缩小的动画效果

修复Flutter心形缩放动画问题

我来帮你搞定这个动画问题!先拆解下你代码里的问题,再给你完整的修复方案:

问题根源

  1. 动画指令冲突:你在_animate()里同时调用了forward()和reverse(),这两个操作会互相干扰——reverse(from:1.0)会立刻让动画从1.0的缩放值开始往回走,直接覆盖了forward()的执行逻辑,所以你看到心形一开始就处于大尺寸,然后慢慢缩小。
  2. 曲线适配不当:Curves.elasticOut是一个在动画结束时带弹性回弹的曲线,但你需要的是“从小放大→再缩小”的双向动效,单一曲线无法完美适配两个阶段的视觉效果。

修复方案

我们可以用TweenSequence来拆分动画的两个阶段,分别为放大和缩小设置合适的曲线,同时修正动画的执行逻辑:

完整修复代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

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

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

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

  void _animate() {
    // 重置动画后,只需要执行一次forward就能完成整个"放大→缩小"的周期
    _heartController.reset();
    _heartController.forward();
  }

  @override
  void initState() {
    super.initState();
    final animationDuration = const Duration(milliseconds: 800);
    _heartController = AnimationController(duration: animationDuration, vsync: this);
    
    // 用TweenSequence拆分动画阶段:先弹性放大,再平滑缩小
    _heartAnimation = TweenSequence([
      TweenSequenceItem(
        // 从0放大到1.2,用elasticOut实现弹性效果
        tween: Tween(begin: 0.0, end: 1.2).chain(CurveTween(curve: Curves.elasticOut)),
        weight: 0.5, // 占总时长的50%
      ),
      TweenSequenceItem(
        // 从1.2缩小到1.0(图标原始尺寸),用easeIn实现平滑减速
        tween: Tween(begin: 1.2, end: 1.0).chain(CurveTween(curve: Curves.easeIn)),
        weight: 0.5,
      ),
    ]).animate(_heartController);
  }

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

关键改进点

  • 拆分动画阶段:通过TweenSequence将动画拆分为“弹性放大”和“平滑缩小”两个部分,分别搭配适合的曲线,让动效更自然
  • 修正执行逻辑:_animate()方法不再同时触发forward和reverse,一次forward就能完成完整的动画周期
  • 优化时长与曲线:调整总时长为800ms,让弹性放大和后续缩小的节奏更协调
  • 规范代码写法:添加了super.key等符合Flutter最新规范的写法

如果你需要的是“放大到最大后直接缩小回初始的0尺寸”,只需要修改TweenSequence的目标值即可:

_heartAnimation = TweenSequence([
  TweenSequenceItem(
    tween: Tween(begin: 0.0, end: 1.0).chain(CurveTween(curve: Curves.easeOut)),
    weight: 0.5,
  ),
  TweenSequenceItem(
    tween: Tween(begin: 1.0, end: 0.0).chain(CurveTween(curve: Curves.easeIn)),
    weight: 0.5,
  ),
]).animate(_heartController);

内容的提问来源于stack exchange,提问作者rafaelcb21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:09:04