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

Flutter中AnimatedSize组件缩小容器尺寸时无动画效果,仅放大时生效

问题原因分析

你遇到的问题核心在于直接强制将子组件高度设为0,导致AnimatedSize无法捕捉到平滑的尺寸变化过程。当你把_height设为0时,Steps组件里的ListView被瞬间压缩到0高度,尺寸跳变过于突兀,AnimatedSize没有机会生成过渡动画帧,所以看起来是直接收起的。

解决方案

我们需要让子组件的尺寸变化是自然的布局变化,而非外部强制设置高度,这样AnimatedSize才能正确监听并生成动画。具体修改如下:

1. 调整Steps组件逻辑

移除Steps中强制设置高度的代码,改为通过控制列表项数量来控制组件高度:

class Steps extends StatelessWidget {
  const Steps({
    Key? key,
    required this.isExpanded, // 添加展开状态控制参数
  }) : super(key: key);

  final bool isExpanded;

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        padding: EdgeInsets.zero,
        shrinkWrap: true,
        itemBuilder: (context, index) => Column(
              children: [
                ListTile(
                  dense: true,
                  leading: Text('# ${index + 1}'),
                  title: Text(
                    kRecipeSteps[index],
                    style: TextStyle(fontSize: 22, color: Colors.white),
                  ),
                ),
                Divider(
                  color: Colors.white,
                  thickness: 1.0,
                ),
              ],
            ),
        // 根据展开状态动态控制列表项数量
        itemCount: isExpanded ? kRecipeSteps.length : 0);
  }
}

2. 简化主组件结构与逻辑

去掉冗余的_height变量,直接通过_isExpanded状态控制Steps的显示,同时简化AnimatedSize的嵌套层级:

class HomeScreen extends StatefulWidget {
  const HomeScreen({Key? key}) : super(key: key);

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

class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
  double? screenWidth;
  double? screenHeight;
  bool _isExpanded = false;
  Color _color = Colors.grey.withOpacity(0.75);

  void _updateSize() {
    setState(() {
      _isExpanded = !_isExpanded;
    });
  }

  @override
  Widget build(BuildContext context) {
    screenWidth = MediaQuery.of(context).size.width;
    screenHeight = MediaQuery.of(context).size.height;
    return Scaffold(
      body: Center(
        child: GestureDetector(
          onTap: _updateSize,
          // 简化嵌套,让AnimatedSize直接包裹带样式的容器
          child: AnimatedSize(
            vsync: this,
            duration: Duration(milliseconds: 500),
            curve: Curves.easeInOut, // 使用双向平滑曲线优化动画体验
            child: Container(
              padding: EdgeInsets.all(25),
              decoration: BoxDecoration(
                color: _color,
                borderRadius: BorderRadius.circular(20),
              ),
              child: Steps(isExpanded: _isExpanded),
            ),
          ),
        ),
      ),
    );
  }
}
为什么这样修改有效?
  • 当_isExpanded为false时,Steps的itemCount变为0,ListView会自然收缩到0高度,这个尺寸变化是布局层面的渐变过程,AnimatedSize能完整捕捉到并生成过渡动画。
  • 简化嵌套结构后,约束传递更清晰,避免了多层容器导致的尺寸计算异常。
  • 使用Curves.easeInOut曲线,让放大和缩小动画都更自然流畅,不会出现生硬的加速/减速效果。

内容的提问来源于stack exchange,提问作者who-aditya-nawandar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:37:45