下拉按钮错误。应该只有一项具有 [DropdownButton] 的值,

Error in DropdownButton. There should be exactly one item with [DropdownButton]'s value,

我已经在 ListView 中创建了 DropdownBotton,并且我有一个需要在 DropdownMenuItem 中显示的值列表。

我有 2 个关于 DropdownBotton 的问题,

  1. 如何为我的方案设置 DropdownButton 中的默认值。
  2. (控制台错误)
There should be exactly one item with [DropdownButton]'s value: $ 5.50 Pineapple Jack (S). 
Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
'package:flutter/src/material/dropdown.dart':
Failed assertion: line 915 pos 15: 'items == null || items.isEmpty || value == null ||
              items.where((DropdownMenuItem<T> item) {
                return item.value == value;
              }).length == 1'

下面是我的代码:

ListView.builder(
  scrollDirection: Axis.vertical,
  shrinkWrap: true,
  physics: const ScrollPhysics(),
  itemCount: snapshot.data!.length,
  itemBuilder: (_, index) {

    List<String> selectedItemValue = <String>[
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type1}"),
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type2}"),
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type3}")];
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          margin: const EdgeInsets.symmetric(
              horizontal: 10, vertical: 5),
          padding: const EdgeInsets.all(5.0),
          child: DropdownButtonHideUnderline(
                child: DropdownButton<String>(
                  value: dropdownValue,
                  items: selectedItemValue.map((dropValue) {
                  return DropdownMenuItem<String>(
                              value: dropValue,
                              child: Text(dropValue),
                            );
                          }).toList(),
                          onChanged:
                              (newDropdownValue) {
                            setState(() {
                              dropdownValue =
                              newDropdownValue!;
                              print(
                                  'dropdown: $dropdownValue');
                            });
                          },
                        ),
                      ),
                ),
        ],
    );
  }
),

请有人帮助我解决这个问题,在此先感谢。

你的问题是给你的下拉列表一个 value 可能会在你的列表中复制。这意味着您的字符串列表可能包含多个具有相同字符串的项目。为了解决这个问题,你需要给 value 参数一个唯一的值。在这种情况下,您可以在下面的代码中使用数组的索引。

我试图用虚拟列表复制你的代码,这样我就可以 运行 并测试它。

class _StarterPageState extends State<StarterPage> {
  Map<int, int?> dropdownValues = {};

  final List<String> _list = [
    'List Item 1',
    'List Item 2',
    'List Item 3',
    'List Item 4',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        scrollDirection: Axis.vertical,
        shrinkWrap: true,
        physics: const ScrollPhysics(),
        itemCount: _list.length,
        itemBuilder: (_, parentListIndex) {
          List<String> selectedItemValues = <String>[
            'Dropdown Item 1',
            'Dropdown Item 2',
            'Dropdown Item 3',
            'Dropdown Item 4',
          ];

          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
                padding: const EdgeInsets.all(5.0),
                child: DropdownButtonHideUnderline(
                  child: DropdownButton<int>(
                    hint: const Text('Select Item'), // Shown when value is null
                    // ?? (selectedItemValues.isNotEmpty ? 0 : null) => this adds a default value if the value is null
                    value: dropdownValues[parentListIndex] ?? (selectedItemValues.isNotEmpty ? 0 : null),
                    items: List.generate(
                      selectedItemValues.length,
                      (i) => DropdownMenuItem<int>(
                        value: i,
                        child: Text(selectedItemValues[i]),
                      ),
                    ),
                    onChanged: (newDropdownValue) {
                      setState(() {
                        dropdownValues[parentListIndex] = newDropdownValue!;
                        print('dropdown: ${dropdownValues[parentListIndex]}');
                      });
                    },
                  ),
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

此外,由于您有多个下拉菜单,因此需要将下拉菜单的值分开,所以这就是我创建具有以下结构的地图的原因:

{
   <parentListIndex>: <dropdownValueIndex>,
   <parentListIndex>: <dropdownValueIndex>,
  //...
}

您可以将 hint 参数添加到您的 DropdownButton 小部件,如下所示:

DropdownButton<int>(
   hint: const Text('Select Item'),
   value: dropdownValueIndex,
   //...
)

查看此 DartPad 中的现场演示 https://dartpad.dev/?id=08ace6b8f73cff0216673dcf9def433d

DropdownButton's value should be unique among DropdownMenuItem' 值并且项目中必须有一个 DropDownMenuItemDropDownButton 的当前值完全匹配。 在您的情况下,您没有从 selectedItemValue 设置 DropdownButtons 值。因此,您的问题的答案是,

  1. 设置 DropdownButton 的初始值作为 selectedItemValue 的默认值。

  2. 为避免错误,请将 DropdownButton 移至分隔 StatefullWidget(本例中为 CustomDropdownButton)。按如下方式更改您的代码。

ListView.builder(
  scrollDirection: Axis.vertical,
  shrinkWrap: true,
  physics: const ScrollPhysics(),
  itemCount: snapshot.data!.length,
  itemBuilder: (_, index) {

    List<String> selectedItemValue = <String>[
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type1}"),
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type2}"),
    ("$${snapshot.data![index].price} ${snapshot.data![index].productType.type3}")];

final defaultValue = selectedItemValue[1];

        return CustomDropdownButton(defaultValue:defaultValue, values: selectedItemValue, onItemSelected: (value) {print("Selected Item : $value");});
      }
    ),

CustomDropdownButton class

class CustomDropdownMenu extends StatefulWidget {
  const CustomDropdownMenu(
      {Key? key,
      required this.defaultValue,
      required this.values,
      required this.onItemSelected})
      : super(key: key);
  final dynamic Function(String? selectedValue) onItemSelected;
  final String defaultValue;
  final List<String> values;
  @override
  _CustomDropdownMenuState createState() => _CustomDropdownMenuState();
}

class _CustomDropdownMenuState extends State<CustomDropdownMenu> {
  late String dropdownValue;

  @override
  void initState() {
    super.initState();
    dropdownValue = widget.defaultValue;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Container(
          margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
          padding: const EdgeInsets.all(5.0),
          child: DropdownButtonHideUnderline(
            child: DropdownButton<String>(
              value: dropdownValue,
              items: widget.values.map((dropValue) {
                return DropdownMenuItem<String>(
                  value: dropValue,
                  child: Text(dropValue),
                );
              }).toList(),
              onChanged: (newDropdownValue) {
                setState(() {
                  dropdownValue = newDropdownValue!;
                });
                widget.onItemSelected(newDropdownValue);
              },
            ),
          ),
        ),
      ],
    );
  }
}