如何在flutter中实现下拉列表?

问题描述 投票:25回答:12

我有一个我希望在Flutter中作为下拉列表实现的位置列表。我对这门语言很陌生。这就是我所做的。

new DropdownButton(
  value: _selectedLocation,
  onChanged: (String newValue) {
    setState(() {
      _selectedLocation = newValue;
     });
},
items: _locations.map((String location) {
  return new DropdownMenuItem<String>(
     child: new Text(location),
  );
}).toList(),

这是我的项目清单:

List<String> _locations = ['A', 'B', 'C', 'D'];

我收到以下错误。

Another exception was thrown: 'package:flutter/src/material/dropdown.dart': Failed assertion: line 468 pos 15: 'value == null || items.where((DropdownMenuItem<T> item) => item.value == value).length == 1': is not true.

我假设_selectedLocation的值变为null。但我正在初始化它。

String _selectedLocation = 'Please choose a location';

drop-down-menu dart flutter
12个回答
27
投票

试试这个

new DropdownButton<String>(
  items: <String>['A', 'B', 'C', 'D'].map((String value) {
    return new DropdownMenuItem<String>(
      value: value,
      child: new Text(value),
    );
  }).toList(),
  onChanged: (_) {},
)

0
投票

当我遇到这个想要一个不太通用的DropdownStringButton的问题时,我只是创建了它:

dropdown_string_button.dart

    FlutterSearchPanel(
        padding: EdgeInsets.all(10.0),
        selected: 'a',
        title: 'Demo Search Page',
        data: ['This', 'is', 'a', 'test', 'array'],
        icon: new Icon(Icons.label, color: Colors.black),
        color: Colors.white,
        textStyle: new TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 20.0, decorationStyle: TextDecorationStyle.dotted),
        onChanged: (value) {
          print(value);
        },
   ),

0
投票

当我用新的动态值替换默认值时,我发生了这种情况。但是,不知何故,您的代码可能依赖于该默认值。因此,请尝试保留一个常量,并将默认值存储在某处以进行回退。

List _currency = ["INR", "USD", "SGD", "EUR", "PND"];
List<DropdownMenuItem<String>> _dropDownMenuCurrencyItems;
String _currentCurrency;

List<DropdownMenuItem<String>> getDropDownMenuCurrencyItems() {
  List<DropdownMenuItem<String>> items = new List();
  for (String currency in _currency) {
    items.add(
      new DropdownMenuItem(value: currency, child: new Text(currency)));
  }
  return items;
}

void changedDropDownItem(String selectedCurrency) {
  setState(() {
    _currentCurrency = selectedCurrency;
  });
}

0
投票

更改

new Row(children: <Widget>[
  new Text("Currency: "),
  new Container(
    padding: new EdgeInsets.all(16.0),
  ),
  new DropdownButton(
    value: _currentCurrency,
    items: _dropDownMenuCurrencyItems,
    onChanged: changedDropDownItem,
  )
])

import 'package:flutter/material.dart';
// Subclass of DropdownButton based on String only values.
// Yes, I know Flutter discourages subclassing, but this seems to be
// a reasonable exception where a commonly used specialization can be
// made more easily usable.
//
// Usage: 
// DropdownStringButton(items: ['A', 'B', 'C'], value: 'A', onChanged: (string) {})
//
class DropdownStringButton extends DropdownButton<String> {
  DropdownStringButton({
    Key key, @required List<String> items, value, hint, disabledHint,
    @required onChanged, elevation = 8, style, iconSize = 24.0, isDense = false,
    isExpanded = false, }) : 
    assert(items == null || value == null || items.where((String item) => item == value).length == 1),
        super(
          key: key,
          items: items.map((String item) {
            return DropdownMenuItem<String>(child: Text(item), value: item);
          }).toList(),
        value: value, hint: hint, disabledHint: disabledHint, onChanged: onChanged,
        elevation: elevation, style: style, iconSize: iconSize, isDense: isDense,
        isExpanded: isExpanded,
        );
    }

_selectedLocation需要成为项目列表的一部分;


8
投票

首先,让我们来研究一下错误的含义(我已经引用了Flutter 1.2引发的错误,但想法是一样的):

断言失败:第560行pos 15:'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem item)=> item.value == value)。length == 1':不是真的。

有四个or条件。必须至少完成其中一项:

  • 提供了项目(DropdownMenuItem小部件列表)。这消除了items == null
  • 提供了非空列表。这消除了items.isEmpty
  • 还给出了值(_selectedLocation)。这消除了value == null。请注意,这是DropdownButton的值,而不是DropdownMenuItem的值。

因此只留下最后一次检查。归结为:

通过DropdownMenuItem迭代。找到所有有value等于_selectedLocation的人。然后,检查找到与其匹配的项目数。必须只有一个具有此值的窗口小部件。否则,抛出一个错误。

代码的呈现方式,没有DropdownMenuItem小部件,其值为_selectedLocation。相反,所有小部件的值都设置为null。自null != _selectedLocation以来,最后一个条件失败了。通过将_selectedLocation设置为null来验证这一点 - 应该运行应用程序。

要解决这个问题,我们首先需要在每个DropdownMenuItem上设置一个值(以便可以将某些内容传递给onChanged回调):

return DropdownMenuItem(
    child: new Text(location),
    value: location,
);

该应用程序仍然会失败。这是因为您的列表仍然不包含_selectedLocation的值。您可以通过两种方式使应用程序工作:

  • 选项1.添加具有值的另一个窗口小部件(以满足items.where((DropdownMenuItem<T> item) => item.value == value).length == 1)。如果您想让用户重新选择Please choose a location选项,可能会有用。
  • 选项2.将一些东西传递给qazxsw poi参数并将qazxsw poi设置为qazxsw poi(以满足hint:条件)。如果您不希望selectedLocation仍然是一个选项,这很有用。

请参阅下面的代码,说明如何执行此操作:

null

7
投票

你必须考虑到这一点(来自DropdownButton docs):

“这些项目必须具有不同的值,如果值不为空,则必须包含它们。”

所以基本上你有这个字符串列表

value == null

您在Dropdown值属性中的值初始化如下:

Please choose a location

试试这个清单:

import 'package:flutter/material.dart';

void main() {
  runApp(Example());
}

class Example extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _ExampleState();
}

class _ExampleState extends State<Example> {
//  List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D']; // Option 1
//  String _selectedLocation = 'Please choose a location'; // Option 1
  List<String> _locations = ['A', 'B', 'C', 'D']; // Option 2
  String _selectedLocation; // Option 2

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: DropdownButton(
            hint: Text('Please choose a location'), // Not necessary for Option 1
            value: _selectedLocation,
            onChanged: (newValue) {
              setState(() {
                _selectedLocation = newValue;
              });
            },
            items: _locations.map((location) {
              return DropdownMenuItem(
                child: new Text(location),
                value: location,
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

那应该工作:)

如果您不想添加类似的字符串(在列表上下文中),请查看“提示”属性,您可以使用以下内容:

List<String> _locations = ['A', 'B', 'C', 'D'];

5
投票

您需要在代码中添加String _selectedLocation = 'Please choose a location'; 才能使用它。检查List<String> _locations = ['Please choose a location', 'A', 'B', 'C', 'D']; 了。

DropdownButton<int>(
          items: locations.map((String val) {
                   return new DropdownMenuItem<String>(
                        value: val,
                        child: new Text(val),
                         );
                    }).toList(),
          hint: Text("Please choose a location"),
          onChanged: (newVal) {
                  _selectedLocation = newVal;
                  this.setState(() {});
                  });

4
投票

将值放在items.then它将工作,

value: location

2
投票

您可以使用this类来创建下拉列表:

items: _locations.map((String location) {
  return new DropdownMenuItem<String>(
     child: new Text(location),
     value: location,
  );
}).toList(),

请参考这个new DropdownButton<String>( items:_dropitems.map((String val){ return DropdownMenuItem<String>( value: val, child: new Text(val), ); }).toList(), hint:Text(_SelectdType), onChanged:(String val){ _SelectdType= val; setState(() {}); })


0
投票

当我试图在下拉列表中显示动态字符串列表时,我遇到了与DropDownButton类似的问题。我最终创建了一个插件:DropDownButton。不是下拉插件,但您可以使用搜索功能显示项目。

使用以下代码来使用窗口小部件:

...
...
String dropdownValue = 'One';
...
...
Widget build(BuildContext context) {
return Scaffold(
  body: Center(
    child: DropdownButton<String>(
      value: dropdownValue,
      onChanged: (String newValue) {
        setState(() {
          dropdownValue = newValue;
        });
      },
      items: <String>['One', 'Two', 'Free', 'Four']
          .map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
    ),
  ),
);
...
...

0
投票

假设我们正在创建一个货币下拉列表:

flutter web page

在正文部分添加以下代码:

flutter_search_panel

0
投票

您获得的错误是由于要求null对象的属性。您的项目必须为null,因此在要求比较其值时,您将收到该错误。检查您是否正在获取数据,或者列表是对象列表而不是简单字符串。

© www.soinside.com 2019 - 2024. All rights reserved.