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

Flutter中如何在同一区域仅显示多个Widget中的一个?

优雅切换Flutter Widget的几种方案

1. 条件表达式(最简洁直接)

用一个布尔变量控制显示逻辑,初始状态显示widget1,点击按钮后切换变量值,直接返回对应widget。这种方式不需要额外布局组件,完全按需渲染,避免了Column/Row选择的纠结。

示例代码:

bool _showMore = false;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      // 直接根据状态返回要显示的Widget
      child: _showMore ? Widget2() : Widget1(
        onViewMore: () => setState(() => _showMore = true),
      ),
    ),
  );
}

// 基础信息Widget示例
class Widget1 extends StatelessWidget {
  final VoidCallback onViewMore;
  const Widget1({super.key, required this.onViewMore});

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        const Text("姓名:张三"),
        const Text("年龄:28"),
        ElevatedButton(
          onPressed: onViewMore,
          child: const Text("查看更多信息"),
        ),
      ],
    );
  }
}

// 更多信息Widget示例
class Widget2 extends StatelessWidget {
  const Widget2({super.key});

  @override
  Widget build(BuildContext context) {
    return const Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text("姓名:张三"),
        Text("年龄:28"),
        Text("职业:Flutter开发"),
        Text("邮箱:zhangsan@example.com"),
      ],
    );
  }
}

2. IndexedStack(保留Widget状态)

如果需要保留两个Widget的状态(比如切换回widget1时不想丢失之前的操作),可以用IndexedStack,通过控制index值切换显示的Widget,它会预加载所有子Widget并保留状态。

示例代码:

int _currentTab = 0;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: IndexedStack(
        index: _currentTab,
        children: [
          Widget1(
            onViewMore: () => setState(() => _currentTab = 1),
          ),
          const Widget2(),
        ],
      ),
    ),
  );
}

3. AnimatedSwitcher(带切换动画)

想要切换时的过渡效果提升体验?用AnimatedSwitcher可以轻松实现淡入淡出、缩放等动画,只需要设置动画时长和过渡方式。

示例代码:

bool _showMore = false;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: AnimatedSwitcher(
        duration: const Duration(milliseconds: 300),
        // 自定义过渡动画,这里用淡入淡出
        transitionBuilder: (child, animation) => FadeTransition(
          opacity: animation,
          child: child,
        ),
        // 注意给每个子Widget设置唯一key,确保AnimatedSwitcher能识别切换
        child: _showMore 
            ? const Widget2(key: ValueKey("more")) 
            : Widget1(
                key: const ValueKey("basic"),
                onViewMore: () => setState(() => _showMore = true),
              ),
      ),
    ),
  );
}

为什么不推荐Column+可见性?

这种方式会同时渲染两个Widget,只是隐藏其中一个,既浪费性能,还得额外处理布局对齐问题;而上面的方案要么只渲染当前需要的Widget,要么针对状态保留/动画场景做了优化,更符合Flutter的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:40:28