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

Flutter 中如何实现点击按钮后动态变更 Dialog 内容

Flutter Dialog内部内容切换实现方案

核心思路

默认Dialog是无状态组件,无法通过页面级的setState刷新内部UI,所以需要用StatefulBuilder包裹Dialog的内容区域,拿到Dialog内部独立的状态更新方法来控制内容切换。

完整可运行示例代码

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Dialog切换示例')),
        body: Center(
          child: ElevatedButton(
            onPressed: () => _showCustomDialog(context),
            child: const Text('打开弹窗'),
          ),
        ),
      ),
    );
  }

  void _showCustomDialog(BuildContext context) {
    // 定义表单输入控制器
    final TextEditingController _nameController = TextEditingController();
    final TextEditingController _phoneController = TextEditingController();

    showDialog(
      context: context,
      builder: (context) {
        // 控制内容切换的状态变量
        bool _isShowForm = false;
        return AlertDialog(
          title: const Text('操作弹窗'),
          // 用StatefulBuilder包裹内容区域,获取内部setState
          content: StatefulBuilder(
            builder: (context, setState) {
              return Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  // 条件渲染不同内容
                  if (!_isShowForm)
                    // 初始按钮列表
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        ElevatedButton(
                          onPressed: () {
                            // 调用StatefulBuilder的setState更新状态
                            setState(() {
                              _isShowForm = true;
                            });
                          },
                          child: const Text('填写信息'),
                        ),
                        const SizedBox(height: 12),
                        ElevatedButton(
                          onPressed: () => Navigator.pop(context),
                          child: const Text('取消'),
                        ),
                      ],
                    )
                  else
                    // 切换后的表单内容
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        TextField(
                          controller: _nameController,
                          decoration: const InputDecoration(labelText: '姓名'),
                        ),
                        const SizedBox(height: 12),
                        TextField(
                          controller: _phoneController,
                          decoration: const InputDecoration(labelText: '手机号'),
                          keyboardType: TextInputType.phone,
                        ),
                        const SizedBox(height: 16),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            TextButton(
                              onPressed: () {
                                // 返回按钮列表
                                setState(() {
                                  _isShowForm = false;
                                });
                              },
                              child: const Text('返回'),
                            ),
                            ElevatedButton(
                              onPressed: () {
                                // 处理表单提交逻辑
                                debugPrint('姓名:${_nameController.text},手机号:${_phoneController.text}');
                                Navigator.pop(context);
                              },
                              child: const Text('提交'),
                            ),
                          ],
                        )
                      ],
                    )
                ],
              );
            },
          ),
        );
      },
    );
  }
}

关键注意点

  • 必须使用StatefulBuilder传入的setState方法修改状态,页面级的setState无法触发Dialog内部UI刷新
  • 表单的TextEditingController要定义在showDialog方法内部,不要定义在StatefulBuilder的builder中,避免状态刷新时控制器被重置
  • 如果需要切换动画,可使用AnimatedSwitcher包裹条件渲染的内容块,自定义过渡效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:57:05