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

Flutter:如何实现AnimatedContainer在固定高度与填充空间间动画过渡

解决AnimatedContainer在固定高度与填充空间之间的过渡动画问题

我明白你想实现的效果:当selectedTab为1时,AnimatedContainer使用固定高度并播放动画;当selectedTab为0时,它要填充剩余的可用空间。你之前用Expanded包裹的方式没达到预期,核心问题出在null值无法触发动画,且Expanded会强制子组件填充空间,覆盖了你设置的height属性。

问题分析

在你的原代码中,当selectedTab == 0时,imageHeight设为null,但AnimatedContainer无法在null和具体数值之间创建过渡动画。同时,Expanded的作用是让子组件占据Column中的剩余空间,这会直接忽略你设置的height值,导致动画完全失效。

解决方案:用LayoutBuilder获取可用空间

我们可以用LayoutBuilder来获取当前可用的最大高度,然后让AnimatedContainer在固定高度和可用最大高度之间做动画,这样就不需要Expanded了,因为我们明确指定了两个具体的数值作为动画的起止值。

修改后的完整代码如下:

class _PreviewScreenState extends State<PreviewScreen> {
  var selectedTab = 1;
  @override
  Widget build(BuildContext context) {
    double imageWidth = MediaQuery.of(context).size.width;
    return Scaffold(
      body: DefaultTabController(
        length: 3,
        initialIndex: selectedTab,
        child: Background(
          child: SafeArea(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                AppBar(
                  backgroundColor: Colors.transparent,
                  elevation: 0,
                  title: Text('SHARE'),
                ),
                // 用LayoutBuilder替代Expanded,获取可用空间高度
                LayoutBuilder(
                  builder: (context, constraints) {
                    return AnimatedContainer(
                      // 当selectedTab为0时,用可用最大高度;为1时用固定宽度对应的高度
                      height: selectedTab == 1 ? imageWidth : constraints.maxHeight,
                      duration: Duration(milliseconds: 600),
                      color: Colors.red,
                    );
                  },
                ),
                TabBar(
                  labelStyle: TextStyle(fontSize: 13),
                  indicator: BoxDecoration(
                    color: Colors.white24,
                    borderRadius: BorderRadius.circular(40),
                  ),
                  onTap: (index) {
                    setState(() {
                      selectedTab = index;
                    });
                  },
                  tabs: <Widget>[
                    Tab(child: Text('INSTAGRAM')),
                    Tab(child: Text('SQUARE')),
                    Tab(child: Text('OTHER'))
                  ],
                ),
                Container(
                  height: 100,
                  child: Center(
                    child: Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 20.0),
                      child: ShareButton(
                        onPressed: () {},
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

关键改动说明

  1. 移除Expanded,使用LayoutBuilder:LayoutBuilder会提供当前父组件的约束条件,constraints.maxHeight就是Column中留给中间区域的可用高度(减去AppBar、TabBar和底部Container的高度)。
  2. 明确动画的起止值:现在height始终是具体的数值(要么是imageWidth,要么是constraints.maxHeight),AnimatedContainer可以完美在这两个值之间创建平滑的过渡动画。
  3. 保留原有逻辑:TabBar的切换逻辑和其他组件保持不变,只修改了中间容器的实现方式。

这样修改后,你就能看到AnimatedContainer在固定高度和填充空间之间流畅切换的动画效果了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:02:00