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

如何根据字符串值动态构建并显示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),
      ),
    );
  }
}

关键改动说明

  1. 状态更新必须调用setState:
    之前的onTap仅修改displayText但未触发状态更新,Flutter无法感知变化,自然不会刷新UI。现在每个按钮的onTap都用setState包裹状态修改,确保UI能实时响应变化。

  2. 新增_getDisplayWidget方法:
    把根据状态匹配Widget的逻辑抽成单独方法,让build代码更简洁。通过switch判断当前状态,返回对应Widget——这种方式只会构建当前需要的Widget,不会像Visibility那样提前加载所有Widget到内存,性能更优,尤其当Widget数量多、逻辑复杂时差异更明显。

  3. 替换中间容器内容:
    将原来显示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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 13:35:20