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

Flutter模态框中Dropdown组件值无法实时变更问题

解决Flutter模态框中Dropdown选中值无法实时更新的问题

问题核心在于模态框拥有独立于父Widget的上下文,你当前调用的setState属于打开模态框的父组件,只会触发父Widget的重建,无法影响模态框内部的Dropdown状态,所以选中值必须等模态框关闭后才会同步显示。

下面是两种可行的解决方法:

方法一:用StatefulBuilder包裹Dropdown区域

在模态框内部通过StatefulBuilder创建局部状态管理环境,让Dropdown的状态更新能实时生效:

var chosenRecentDay = 1;
List<int> daysList = [for (var i = 1; i < 31; i++) i];
int defaultDropDownValue = 1;

showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
    return SizedBox(
      height: 500.0,
      child: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              // 用StatefulBuilder包裹Dropdown,获取局部状态更新方法
              StatefulBuilder(
                builder: (context, setState) {
                  return SizedBox(
                    width: 150.0,
                    height: 45.0,
                    child: Center(
                      child: DropdownButton(
                        value: defaultDropDownValue,
                        menuMaxHeight: 250.0,
                        icon: const Icon(
                          Icons.arrow_drop_down_circle_rounded,
                          color: Color(0xffF85E63),
                        ),
                        borderRadius: BorderRadius.circular(30.0),
                        alignment: Alignment.center,
                        underline: Container(color: Colors.transparent),
                        items: daysList
                            .map<DropdownMenuItem<dynamic>>((dynamic value) {
                          var convertedList = value.toString();
                          return DropdownMenuItem<dynamic>(
                            value: value,
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.start,
                              children: <Widget>[
                                Padding(
                                  padding:
                                      const EdgeInsets.symmetric(horizontal: 5.0),
                                  child: Text(
                                    convertedList,
                                    style: const TextStyle(
                                      color: Color(0xffF85E63),
                                      fontFamily: 'Lalezar',
                                      fontSize: 18.0,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          );
                        }).toList(),
                        onChanged: (val) {
                          // 此处的setState是StatefulBuilder提供的局部更新方法
                          setState(() {
                            defaultDropDownValue = val!;
                            chosenRecentDay = val;
                          });
                        },
                      ),
                    ),
                  );
                },
              ),
            ],
          ),
        ),
      ),
    );
  },
);

方法二:将模态框内容抽为独立的StatefulWidget

如果模态框逻辑复杂,把它单独封装成StatefulWidget,状态管理会更清晰易维护:

// 独立的模态框组件
class DaySelectorModal extends StatefulWidget {
  final int initialValue;
  final Function(int) onDaySelected;

  const DaySelectorModal({
    super.key,
    required this.initialValue,
    required this.onDaySelected,
  });

  @override
  State<DaySelectorModal> createState() => _DaySelectorModalState();
}

class _DaySelectorModalState extends State<DaySelectorModal> {
  late int _selectedDay;
  final List<int> daysList = [for (var i = 1; i < 31; i++) i];

  @override
  void initState() {
    super.initState();
    _selectedDay = widget.initialValue;
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 500.0,
      child: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              SizedBox(
                width: 150.0,
                height: 45.0,
                child: Center(
                  child: DropdownButton(
                    value: _selectedDay,
                    menuMaxHeight: 250.0,
                    icon: const Icon(
                      Icons.arrow_drop_down_circle_rounded,
                      color: Color(0xffF85E63),
                    ),
                    borderRadius: BorderRadius.circular(30.0),
                    alignment: Alignment.center,
                    underline: Container(color: Colors.transparent),
                    items: daysList
                        .map<DropdownMenuItem<int>>((int value) {
                      return DropdownMenuItem<int>(
                        value: value,
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 5.0),
                          child: Text(
                            value.toString(),
                            style: const TextStyle(
                              color: Color(0xffF85E63),
                              fontFamily: 'Lalezar',
                              fontSize: 18.0,
                            ),
                          ),
                        ),
                      );
                    }).toList(),
                    onChanged: (val) {
                      setState(() {
                        _selectedDay = val!;
                      });
                      widget.onDaySelected(_selectedDay);
                    },
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// 调用模态框的代码
var chosenRecentDay = 1;

showModalBottomSheet(
  context: context,
  builder: (BuildContext context) {
    return DaySelectorModal(
      initialValue: chosenRecentDay,
      onDaySelected: (day) {
        chosenRecentDay = day;
        // 若需同步更新父组件,可在此调用父Widget的setState
        // setState(() {});
      },
    );
  },
);

第一种方法适合快速修复简单场景,第二种更适合复杂模态框的长期迭代维护。

内容的提问来源于stack exchange,提问作者Shervin.bdn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:05:29