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

Flutter DropdownMenu开启enableFilter后选择非第一项触发越界错误

问题:DropdownMenu开启过滤后选择非第一项触发越界错误

开启enableFilter: true后,DropdownMenu选择除第一项外的任何选项都会崩溃,抛出RangeError Index out of range错误;设置enableFilter: false则无此问题。

已完成的排查:

  • 确认LevelOfBadness枚举的每个选项都对应了DropdownMenuEntry
  • 打印日志验证数据类型和值均正常

原因分析

这是Flutter框架的已知问题,和你参考的StackOverflow问题属于同一类场景:当DropdownMenu以枚举作为泛型类型且启用过滤功能时,框架内部处理选中项索引时出现逻辑错误——错误地将枚举自身的索引(比如LevelOfBadness.X的索引为5)直接当作过滤后列表的索引使用,当过滤后的列表长度不足或索引不匹配时,就会触发越界异常。

修复方案

方案1:添加initialSelection绑定选中状态

给DropdownMenu添加initialSelection参数,将其与你的选中变量绑定,让框架能正确关联选中项和列表条目:

DropdownMenu(
  enableFilter: true,
  initialSelection: selectedBadnessRating, // 新增该行
  onSelected: (currentBadnessSelectedInDropdownMenu) {
    if (currentBadnessSelectedInDropdownMenu != null) {
      setState(() {
        log("Type is: " + currentBadnessSelectedInDropdownMenu.runtimeType.toString());
        log("Value is: " + currentBadnessSelectedInDropdownMenu.toString());
        selectedBadnessRating = currentBadnessSelectedInDropdownMenu;
      });
    }
  },
  dropdownMenuEntries: const <DropdownMenuEntry<LevelOfBadness>>[
    DropdownMenuEntry(value: LevelOfBadness.I, label: "Underwhelming"),
    DropdownMenuEntry(value: LevelOfBadness.II, label: "Rookie"),
    DropdownMenuEntry(value: LevelOfBadness.III, label: "Moderate"),
    DropdownMenuEntry(value: LevelOfBadness.IV, label: "Fully-Operational"),
    DropdownMenuEntry(value: LevelOfBadness.V, label: "Level 5 Baddie"),
    DropdownMenuEntry(value: LevelOfBadness.X, label: "Mega-baddie!"),
  ],
),

方案2:改用非枚举类型作为泛型(临时规避)

如果暂时不想依赖框架修复,可以将枚举转换为字符串/整数作为DropdownMenu的泛型类型,通过映射关系关联回枚举值:

// 提前定义映射列表
final List<Map<String, dynamic>> badnessRatingItems = [
  {"enumValue": LevelOfBadness.I, "label": "Underwhelming"},
  {"enumValue": LevelOfBadness.II, "label": "Rookie"},
  {"enumValue": LevelOfBadness.III, "label": "Moderate"},
  {"enumValue": LevelOfBadness.IV, "label": "Fully-Operational"},
  {"enumValue": LevelOfBadness.V, "label": "Level 5 Baddie"},
  {"enumValue": LevelOfBadness.X, "label": "Mega-baddie!"},
];

// 使用String作为泛型的DropdownMenu
DropdownMenu<String>(
  enableFilter: true,
  onSelected: (String? selectedLabel) {
    if (selectedLabel != null) {
      setState(() {
        selectedBadnessRating = badnessRatingItems.firstWhere((item) => item["label"] == selectedLabel)["enumValue"];
      });
    }
  },
  dropdownMenuEntries: badnessRatingItems
      .map((item) => DropdownMenuEntry(value: item["label"], label: item["label"]))
      .toList(),
),

额外解决:重置时清空选中状态

你提到的重置时无法取消选中的问题,只需在重置方法中将selectedBadnessRating设为null,配合方案1的initialSelection就能正常清空:

void onPressedReset()
{
  setState(() {
    tfc.text = "";
    theBiggestVillian = null;
    selectedBadnessRating = null; // 现在可正常清空选中状态
    log("Reset ran");
  });
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:44:52