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

如何让AnimatedSwitcher切换的两张Card保持相同高度?

解决AnimatedSwitcher卡片翻转动画高度突兀问题

方案1:提前测量并固定最大高度

核心思路是先获取两张卡片的实际高度,取最大值作为容器固定高度,让矮卡片顶部对齐、底部留空,模拟“扩展”效果。

  1. 定义全局Key用于测量高度
final GlobalKey _card1Key = GlobalKey();
final GlobalKey _card2Key = GlobalKey();
double _maxCardHeight = 0;
  1. 组件初始化后测量高度
    利用WidgetsBinding的帧回调,在组件首次渲染完成后获取两张卡片的高度:
@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    // 获取两张卡片的渲染对象
    final card1Render = _card1Key.currentContext?.findRenderObject() as RenderBox?;
    final card2Render = _card2Key.currentContext?.findRenderObject() as RenderBox?;
    
    if (card1Render != null && card2Render != null) {
      setState(() {
        _maxCardHeight = max(card1Render.size.height, card2Render.size.height);
      });
    }
  });
}
  1. 构建布局,固定容器高度
    用固定高度的容器包裹AnimatedSwitcher,矮卡片通过Align保持顶部对齐:
Container(
  height: _maxCardHeight,
  width: double.infinity, // 保持卡片宽度一致
  child: AnimatedSwitcher(
    duration: const Duration(milliseconds: 500),
    transitionBuilder: (child, animation) {
      // 翻转动画实现
      final flipTween = Tween(begin: 0.0, end: 1.0).animate(animation);
      return RotationYTransition(turns: flipTween, child: child);
    },
    child: _showCard1 
        ? Align(
            alignment: Alignment.topCenter,
            child: Card(
              key: _card1Key,
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Text("Card one"),
              ),
            ),
          )
        : Align(
            alignment: Alignment.topCenter,
            child: Card(
              key: _card2Key,
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Text("Taller card 2\nwith more text\n" * 5),
              ),
            ),
          ),
  ),
)

方案2:用AnimatedSize实现高度平滑过渡

如果不想提前固定高度,可结合AnimatedSize让容器高度随切换平滑变化,避免突兀跳转:

AnimatedSize(
  duration: const Duration(milliseconds: 500), // 和翻转动画时长保持一致
  child: AnimatedSwitcher(
    duration: const Duration(milliseconds: 500),
    transitionBuilder: (child, animation) {
      final flipTween = Tween(begin: 0.0, end: 1.0).animate(animation);
      return RotationYTransition(turns: flipTween, child: child);
    },
    child: _showCard1
        ? Card(
            key: const ValueKey(1),
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Text("Card one"),
            ),
          )
        : Card(
            key: const ValueKey(2),
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Text("Taller card 2\nwith more text\n" * 5),
            ),
          ),
  ),
)

注意事项

  • 如果卡片文本是动态加载的(比如网络数据),需要在内容更新后重新测量高度;
  • 提前测量方案需要确保两张卡片都被渲染过,可初始用Offstage临时隐藏未显示的卡片,获取高度后再切换;
  • 两种方案都要保证卡片宽度一致,避免切换时出现宽度跳动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:45:14