0

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

关于 DropdownBotton,我有 2 个问题,

  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');
                            });
                          },
                        ),
                      ),
                ),
        ],
    );
  }
),

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

4

2 回答 2

1

您的问题是为您的下拉列表提供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

于 2021-12-30T11:31:04.403 回答
1

DropdownButton' 的值在 ' 值中应该是唯一的,DropdownMenuItem并且项目中必须有一个DropDownMenuItem与 的当前值完全匹配DropDownButton。在您的情况下,您没有设置DropdownButtons 的值 selectedItemValue。因此,您的问题的答案是,

  1. 设置DropdownButton你想要的初始值作为你的默认值selectedItemValue

  2. 为避免错误,请将您的DropdownButton移到单独的位置StatefullWidgetCustomDropdownButton在这种情况下。)。如下更改您的代码。

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 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);
              },
            ),
          ),
        ),
      ],
    );
  }
}
于 2021-12-30T12:09:11.707 回答