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

Flutter中如何为子组件出现时的重定位添加平滑动画?

实现布局重定位的平滑动画效果

要解决显示容器时Center组件重定位的突兀问题,我们可以通过Flutter的动画组件让尺寸变化和布局调整过程平滑过渡,以下是两种实用方案:

方案一:使用AnimatedSize自动处理尺寸过渡

AnimatedSize会监听子组件的尺寸变化,并自动生成平滑的过渡动画,刚好适配你的场景——当额外容器显示时,ListView的高度变化会被AnimatedSize捕捉,进而带动Center的重定位动画。

修改后的代码如下:

class MyWidget extends Stateful Widget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool _showContainer = false;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedSize(
        // 设置动画时长,可根据需求调整
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        child: ListView(
          shrinkWrap: true,
          children: [
            Text(
              'Hello, World!',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            if (_showContainer)
              Container(
                color: Colors.pink,
                width: 100,
                height: 300,
                child: const Text("How to make the apparition smooth and animated"),
              ),
            ElevatedButton(
              onPressed: () => setState(() => _showContainer = true),
              child: const Text("SHOW CONTAINER"),
            ),
          ],
        ),
      ),
    );
  }
}

方案二:用SizeTransition单独控制容器的显示动画

如果只想针对弹出的容器做尺寸动画,同时让整体布局自然跟随调整,可以用SizeTransition包裹要显示的容器,它会沿着指定轴执行尺寸渐变动画。

修改后的代码示例:

class MyWidget extends Stateful Widget {
  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> with SingleTickerProviderStateMixin {
  bool _showContainer = false;
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 300),
      vsync: this,
    );
    _animation = CurvedAnimation(parent: _controller, curve: Curves.easeInOut);
  }

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ListView(
        shrinkWrap: true,
        children: [
          Text(
            'Hello, World!',
            style: Theme.of(context).textTheme.headlineMedium,
          ),
          if (_showContainer)
            SizeTransition(
              sizeFactor: _animation,
              axis: Axis.vertical,
              child: Container(
                color: Colors.pink,
                width: 100,
                height: 300,
                child: const Text("How to make the apparition smooth and animated"),
              ),
            ),
          ElevatedButton(
            onPressed: () {
              setState(() => _showContainer = true);
              _controller.forward();
            },
            child: const Text("SHOW CONTAINER"),
          ),
        ],
      ),
    );
  }
}

说明

  • 两种方案都可以实现平滑的布局重定位效果,你可以根据需求选择:
    • 方案一更简洁,适合需要整体尺寸过渡的场景;
    • 方案二更灵活,能单独控制容器的动画曲线和时长,还可以扩展其他动画效果。
  • 动画时长和曲线可以根据产品需求调整,比如把duration改成200ms让动画更快,或者换用Curves.easeOut让收尾更自然。

内容的提问来源于stack exchange,提问作者Stéphane de Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:47:38