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

