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

Flutter中如何禁止用户在DropdownMenu组件中输入内容?

问题:禁止Flutter Material3 DropdownMenu组件的输入功能

我需要禁止用户在DropdownMenu组件中输入内容,但未找到实现方法,查阅官方文档也无相关信息。当前使用的DropdownMenu组件允许用户输入,想要实现类似DropdownButton2包的不可输入下拉选择效果。

代码实现

class TDSMDropdown extends StatefulWidget {
  final List<String> items;
  final String? value;
  final String? hintText;
  final String? label;
  final void Function(String?)? onSelected;
  final TextEditingController? controller;

  const TDSMDropdown({
    Key? key,
    required this.items,
    this.value,
    this.hintText,
    required this.label,
    this.onSelected,
    this.controller,
  }) : super(key: key);

  @override
  State<TDSMDropdown> createState() => _TDSMDropdownState();
}

class _TDSMDropdownState extends State<TDSMDropdown> {
  // final TextEditingController colorController = TextEditingController();
  String? selectedValue;

  @override
  void initState() {
    super.initState();
    selectedValue = widget.value;
  }

  _handleOnSelected(String? newVal) {
    widget.onSelected!(newVal);
  }

  @override
  Widget build(BuildContext context) {
    return DropdownMenu<String>(
      width: MediaQuery.of(context).size.width,
      enableSearch: false,
      // controller: colorController,
      label: widget.label == null ? null : Text(widget.label!),
      dropdownMenuEntries: widget.items
          .map((e) => DropdownMenuEntry<String>(value: e, label: e))
          .toList(),
      // inputDecorationTheme: _decoration(),
      onSelected: widget.onSelected != null ? _handleOnSelected : null,
    );
  }
}

环境信息

  • Flutter版本 3.7.0
  • Material 3
  • Dart版本 2.19.0

解决方案

可以通过以下两种方式实现DropdownMenu的不可输入效果:

方法一:通过输入主题配置禁用输入

在DropdownMenu的inputDecorationTheme中设置输入框为禁用状态,同时调整样式避免视觉上的禁用感:

@override
Widget build(BuildContext context) {
  return DropdownMenu<String>(
    width: MediaQuery.of(context).size.width,
    enableSearch: false,
    label: widget.label == null ? null : Text(widget.label!),
    dropdownMenuEntries: widget.items
        .map((e) => DropdownMenuEntry<String>(value: e, label: e))
        .toList(),
    onSelected: widget.onSelected != null ? _handleOnSelected : null,
    // 配置输入主题禁用输入并调整样式
    inputDecorationTheme: InputDecorationTheme(
      enabled: false,
      disabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Theme.of(context).colorScheme.outline),
      ),
      disabledTextStyle: TextStyle(color: Theme.of(context).colorScheme.onSurface),
    ),
  );
}

方法二:拦截输入行为并控制文本

通过控制器管理选中值,同时拦截输入框的焦点和输入动作,保留组件视觉样式的同时禁止输入:

@override
Widget build(BuildContext context) {
  final textController = widget.controller ?? TextEditingController(text: selectedValue);
  return DropdownMenu<String>(
    width: MediaQuery.of(context).size.width,
    enableSearch: false,
    controller: textController,
    label: widget.label == null ? null : Text(widget.label!),
    dropdownMenuEntries: widget.items
        .map((e) => DropdownMenuEntry<String>(value: e, label: e))
        .toList(),
    onSelected: (newVal) {
      widget.onSelected?.call(newVal);
      setState(() {
        selectedValue = newVal;
        textController.text = newVal ?? '';
      });
    },
    // 拦截输入相关行为
    textInputAction: TextInputAction.none,
    onTap: () => FocusScope.of(context).unfocus(),
    inputDecorationTheme: InputDecorationTheme(
      enabledBorder: OutlineInputBorder(
        borderSide: BorderSide(color: Theme.of(context).colorScheme.outline),
      ),
    ),
  );
}

注意事项

  • 方法一设置enabled: false会触发组件的禁用状态,必须自定义样式保持视觉上的可用感,避免用户误解。
  • 方法二更灵活,既能禁止输入,又能完全保留组件的原生视觉样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 00:52:40