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
相关产品推荐
相关产品推荐

