如何根据字符串值动态构建并显示Flutter Widget?
解决方案
完整修改代码
class TestPage extends StatefulWidget { const TestPage({Key? key}) : super(key: key); @override State<TestPage> createState() => _TestPageState(); } class _TestPageState extends State<TestPage> { String displayText = 'Choose option'; // 根据当前状态返回对应Widget的方法 Widget _getDisplayWidget() { switch(displayText) { case 'Option A': return const OneOfTheWidgetsToBuild(); case 'Option B': return Container( height: 40, width: 100, color: Colors.blue, child: const Center(child: Text('B')), ); case 'Option C': return Container( height: 40, width: 100, color: Colors.red, child: const Center(child: Text('C')), ); case 'Option D': return Container( height: 40, width: 100, color: Colors.purple, child: const Center(child: Text('D')), ); default: return const Center( child: Text( 'Choose option', style: TextStyle(color: Colors.black), ), ); } } @override Widget build(BuildContext context) { return Scaffold( body: Row( children: [ Expanded( child: Column( children: [ const SizedBox(height: 50), Button( text: 'option A', onTap: () { setState(() { displayText = 'Option A'; }); }, ), const SizedBox(height: 5), Button( text: 'option B', onTap: () { setState(() { displayText = 'Option B'; }); }, ), ], ), ), Expanded( child: Column( children: [ const SizedBox(height: 50), Center( child: Container( height: 40, width: 100, color: Colors.yellow, child: _getDisplayWidget(), // 替换成动态返回的Widget ), ) ], ), ), Expanded( child: Column( children: [ const SizedBox(height: 50), Button( text: 'option C', onTap: () { setState(() { displayText = 'Option C'; }); }, ), const SizedBox(height: 5), Button( text: 'option D', onTap: () { setState(() { displayText = 'Option D'; }); }, ), ], ), ), ], ), ); } } class OneOfTheWidgetsToBuild extends StatelessWidget { const OneOfTheWidgetsToBuild({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( height: 40, width: 100, color: Colors.green, child: const Center(child: Text('A')), ); } } // 假设你的Button组件实现如下 class Button extends StatelessWidget { final String text; final VoidCallback? onTap; const Button({Key? key, required this.text, this.onTap}) : super(key: key); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), color: Colors.grey, child: Text(text), ), ); } }
关键改动说明
状态更新必须调用
setState:
之前的onTap仅修改displayText但未触发状态更新,Flutter无法感知变化,自然不会刷新UI。现在每个按钮的onTap都用setState包裹状态修改,确保UI能实时响应变化。新增
_getDisplayWidget方法:
把根据状态匹配Widget的逻辑抽成单独方法,让build代码更简洁。通过switch判断当前状态,返回对应Widget——这种方式只会构建当前需要的Widget,不会像Visibility那样提前加载所有Widget到内存,性能更优,尤其当Widget数量多、逻辑复杂时差异更明显。替换中间容器内容:
将原来显示Text的部分替换为_getDisplayWidget(),状态更新后中间容器会自动渲染新Widget,旧Widget会被Flutter自动销毁回收。
进阶优化建议
用字符串作为状态标识容易出现拼写错误,推荐用枚举替代:
// 定义枚举 enum SelectedOption { optionA, optionB, optionC, optionD, none } // 修改状态变量 SelectedOption selectedOption = SelectedOption.none; // 更新_getDisplayWidget方法 Widget _getDisplayWidget() { switch(selectedOption) { case SelectedOption.optionA: return const OneOfTheWidgetsToBuild(); case SelectedOption.optionB: return Container(color: Colors.blue, child: const Text('B')); // 其他case... default: return const Text('Choose option'); } } // 按钮onTap修改为 onTap: () { setState(() { selectedOption = SelectedOption.optionA; }); },
枚举类型能在编译期检查错误,避免字符串拼写导致的bug,代码可读性也更强。
内容的提问来源于stack exchange,提问作者Nomad09
相关产品推荐
相关产品推荐

