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

Flutter实现下拉选择器选中项与菜单项差异化样式(语言切换)

Flutter下拉选择器实现选中项与菜单项差异化样式

需求场景

开发语言切换UI时,需要实现:

  • 下拉选择器收起状态:仅显示国旗图标 + 下拉箭头
  • 下拉选择器展开状态:每个菜单项显示国旗图标 + 语言全称

当前代码无法区分选中项与菜单项的显示逻辑,只能统一控制是否显示文本,无法满足需求。

解决方案

核心是利用Flutter DropdownButton的selectedItemBuilder属性,单独定制选中状态的显示样式,与下拉菜单中的项做区分。

修改后的完整代码

1. 重构DropdownButton组件

DropdownButton<String>(
  items: LanguageUtils.getSupportedLanguagesAsStringList()
      .map<DropdownMenuItem<String>>((String langCodeString) {
    final LangCode langCode = LanguageUtils.getLangCodeFromItsStringRep(langCodeString);
    return DropdownMenuItem<String>(
      value: langCodeString,
      // 下拉菜单中的选项:显示国旗+语言全称
      child: buildLanguageRow(langCode: langCode, showText: true),
    );
  }).toList(),
  value: LanguageUtils.getStringRepForLangCode(_chosenLangCode),
  onChanged: (String? value) {
    if (value != null) {
      _chosenLangCode = LanguageUtils.getLangCodeFromItsStringRep(value);
      changeLanguage();
      setState(() {}); // 更新状态刷新UI
    }
  },
  // 定制选中项的显示:仅显示国旗
  selectedItemBuilder: (BuildContext context) {
    return LanguageUtils.getSupportedLanguagesAsStringList().map((String langCodeString) {
      final LangCode langCode = LanguageUtils.getLangCodeFromItsStringRep(langCodeString);
      return buildLanguageRow(langCode: langCode, showText: false);
    }).toList();
  },
);

2. 重构行元素构建方法

/// 构建下拉选择器的行组件
Row buildLanguageRow({required LangCode langCode, required bool showText}) {
  final List<Widget> rowElements = [];
  
  // 始终添加国旗图标
  rowElements.add(getImageOfLangCode(langCode: langCode));
  
  // 根据参数决定是否添加语言文本
  if (showText) {
    rowElements.add(Text(LanguageUtils.getFullNameForLangCode(langCode)));
  }

  return Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: rowElements,
  );
}

3. 保留原LanguageUtils工具类(无需修改)

/// 语言处理工具类
class LanguageUtils {
  LanguageUtils() {}

  static String getFullNameForLangCode(LangCode langCodeToGetStringFor) {
    switch (langCodeToGetStringFor) {
      case LangCode.en:
        return "English";
      case LangCode.de:
        return "Deutsch";
    }
  }

  static String getStringRepForLangCode(LangCode langCodeToGetStringFor) {
    switch (langCodeToGetStringFor) {
      case LangCode.en:
        return "en";
      case LangCode.de:
        return "de";
    }
  }

  static List<String> getSupportedLanguagesAsStringList() {
    return LangCode.values.map((e) => e.name).toList();
  }

  static LangCode getLangCodeFromItsStringRep(String langCodeAsString) {
    switch (langCodeAsString) {
      case "de":
        return LangCode.de;
      case "en":
      default:
        return LangCode.en;
    }
  }
}

enum LangCode { en, de }

关键说明

  • selectedItemBuilder:这个回调专门负责生成选中状态下的显示组件,这里我们只返回国旗图标,不显示文本。
  • items.child:下拉展开后的每个选项使用带文本的样式,通过showText: true控制显示完整内容。
  • 状态更新:在onChanged回调中修改选中语言后,必须调用setState触发UI刷新,确保选中项样式同步切换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 07:17:55