【问题标题】:Dropdown selection not displaying with FlutterFlutter 不显示下拉选择
【发布时间】:2019-02-08 14:27:18
【问题描述】:

我从 JSON 中获取项目并在下拉列表中显示它们。当该人从下拉列表中选择一个项目时,我得到了选择,但所选项目没有改变。

例如,我们在列表中有 (tokyo, paris, new york)。默认选择是东京。当该人选择巴黎时,我明白了,但下拉列表中的选择没有改变。

这是我的代码:

new DropdownButton(
  value: cities.elementAt(0),
  hint: new Text("Ville"),
  items: cities.map((String value) {
    return new DropdownMenuItem(
      value: value,
      child: new Row(
        children: <Widget>[
          new Icon(
            Icons.location_city,
            color: Colors.deepOrange,
          ),
          new Text(value)
        ],
      ),
    );
  }).toList(),
  onChanged: (String value) {
    getTravelCity(value);
  },
),

当人选择一个项目时,它仍然显示默认值。

【问题讨论】:

标签: dart flutter dropdown


【解决方案1】:

确保您没有在 Widget 中声明 selectedValue,下面的示例非常适合我。

这是dartpad 上的工作代码,用于测试它

var currentSelectedValue;
const deviceTypes = ["Mac", "Windows", "Mobile"];

 Widget typeFieldWidget() {
return Container(
  padding: EdgeInsets.symmetric(horizontal: 20),
  child: FormField<String>(
    builder: (FormFieldState<String> state) {
      return InputDecorator(
        decoration: InputDecoration(
            border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(5.0))),
        child: DropdownButtonHideUnderline(
          child: DropdownButton<String>(
            hint: Text("Select Device"),
            value: currentSelectedValue,
            isDense: true,
            onChanged: (newValue) {
              setState(() {
                currentSelectedValue = newValue;
              });
              print(currentSelectedValue);
            },
            items: deviceTypes.map((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
          ),
        ),
      );
    },
  ),
);
}

【讨论】:

  • 如果您使用SetState 就可以了,我需要StatelessWidget
  • 如果不执行 setState 就无法在屏幕上呈现新内容,这就是 Flutter 的工作原理,它需要通过执行 setState 来重绘小部件,您可以更改内存中的变量值但呈现更新的值在屏幕上,您需要通过调用 setState 来重绘 ui;
  • 如果您尝试了上面的代码,它将起作用,如果您想添加新元素,只需将该元素添加到您的列表中,例如上面代码中的deviceTypes,这样新元素就会反映在下拉列表中向下,只要下拉列表在屏幕上呈现,它就会获取新列表。
  • 我已经用工作代码的 dartpad 链接更新了答案,请检查一下
  • 最重要的问题:“确保你没有在 Widget 中声明 selectedValue”!
【解决方案2】:
This is the solution: "StatefulBuilder()"

       Future<void> AgregarContacto() async {
             String dropdownValue = 'Exento';
             return showDialog<void>(
           context: context,
           barrierDismissible: true, // user must tap button!
           builder: (BuildContext context) {
                 return StatefulBuilder(
                   builder: (BuildContext context, StateSetter setState) {
                   return AlertDialog(
                   title: Text('Agregar cliente', textAlign: TextAlign.center,),
                   content:
                     SingleChildScrollView(
                       child: ListBody(
                         children: <Widget>[
                           Center(
                             child: Material(
                               type: MaterialType.transparency,
                               child: DropdownButton<String>(
                                 items: <String>[
                                   'Responsable inscripto',
                                   'Monotributista',
                                   'Exento',
                                   'Consumidor final',
                                   'No responsable'
                                 ]
                                     .map<DropdownMenuItem<String>>((
                                     String value) {
                                   return DropdownMenuItem<String>(
                                     value: value,
                                     child: Text(value),
                                   ); //DropMenuItem
                                 }).toList(),
                                 value: dropdownValue,
                                 onChanged: (String newValue) {
                                   setState(() {
                                     dropdownValue = newValue;
                                     print("new${newValue}");
                                   }); //setState
                                 },
                                 //OnChange
                                 isExpanded: false,
                                 hint: Text('Responsable inscripto',
                                   style: TextStyle(color: Colors.black),),
                               ),
                             ), //Material
                           ), //Center
                         ],
                       ),
                     ),
                   actions: <Widget>[
                         FlatButton(
                           child: Text('Regret'),
                           onPressed: () {
                             Navigator.of(context).pop();
                          },
                       ),
                    ],
                 );
            }
            );
           },
         );
       }

【讨论】:

  • 这正是我想要的。我有一个很长的无状态屏幕,并且希望在该状态下只有一个下拉菜单。这篇文章只是给了我这个。干杯。我测试了它,它就像魅力一样。
【解决方案3】:

这是 Flutter 的 Github 中报告的错误。

正确的实现方式是:

class _DropdownButtonBugState extends State<DropdownButtonBug> {

  final List<String> _items = ['One', 'Two', 'Three', 'Four'].toList();

  String _selection;

  @override
  void initState() {
    _selection = _items.first;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final dropdownMenuOptions = _items
      .map((String item) =>
        new DropdownMenuItem<String>(value: item, child: new Text(item))
      )
      .toList();

    return new Scaffold(
      body: new DropdownButton<String>(
        value: _selection,
        items: dropdownMenuOptions,
        onChanged: (s) {
          setState(() {
            _selection = s;
          });
        }
      )
    );
  }
}

【讨论】:

    【解决方案4】:

    如果在选择后未更新所选值,则可以将下拉按钮包装在 StatefulBuilder() 小部件中。

    【讨论】:

      【解决方案5】:

      对于那些将来面临这个问题的人。使用变量将值设置为 DropdownButton 并在调用 onChanged 时使用 setState 更新变量

      Expanded(child: DropdownButton<String>(
                items: cities.map((String value) {
                  return DropdownMenuItem<String>(
                    value: value,
                    child: Text(value),
                  );
                }).toList(),
                value: city,
                onChanged: (String val) {
                  _onDropDownChanged(val);
                },
              ),)
      

      使用状态更新城市变量

      void _onDropDownChanged(String val) {
          setState(() {
            this.city = val;
          });
        }
      

      欲了解更多信息,请查看下面的链接

      https://github.com/FazalHussain/Flutter-Demo/blob/trip_cost_app/lib/main.dart

      【讨论】:

      • 这让我惊醒了。直到我用了这个
      【解决方案6】:

      因为你需要用“setState(() {});”更新“value:”参数方法和新值必须与传递给“onChanged:”的类型相同。我建议这样做,因为您可以动态更改您的图标。

      1) 在文件顶部声明一个新类;

      class city {
        final String name;
        final IconData icon;
      
        const city({
          this.name,
          this.icon,
        });
      }
      

      2) 在你的小部件状态中添加这个:

      class yourState extend<myWidget>{
      
      List<city> cities = [
          new city(name: "tokio", icon: Icons.location_city),
          new city(name: "paris", icon: Icons.location_city),
          new city(name: "new york", icon: Icons.location_city),
        ];
      
      int index = 0;
      
      Widget drop() {
          return DropdownButton(
              value: cities[index],
              hint: new Text("Ville"),
              items: cities.map((city value) {
                return new DropdownMenuItem(
                  value: value,
                  child: new Row(
                    children: <Widget>[
                      new Icon(
                        value.icon,
                        color: Colors.deepOrange,
                      ),
                      new Text(value.name)
                    ],
                  ),
                );
              }).toList(),
              onChanged: (city value) {
                setState(() {
                  index = cities.indexOf(value);
                  print(index);
                });
                //getTravelCity(value.name);
              });
        }
      
      }
      

      现在在您想要 DropDown 的地方调用“drop()”。再见!!

      【讨论】:

      • 我认为DropdownButton 的value 属性已更新。现在不用分配实际的String Value,您可以只使用索引来代替
      【解决方案7】:

      在我最近的应用程序中使用了此代码并且它有效。也许您可以将其与您的代码进行比较。

      return DropdownButton<String>(
          style: Theme.of(context).textTheme.title,
          items: _persons.map((String val) {
            return new DropdownMenuItem<String>(
              value: val,
              child: new Container(
                child: new Card(
                  child: new Row(children: <Widget>[
                    new Icon(Icons.person),
                    new Text(val),
                  ]),
                ),
              ),
            );
          }).toList(),
          hint: new Card(
              child: new Row(children: <Widget>[
            new Icon(Icons.person),
            new Text("check"),
          ])),
          value: _selectedPerson,
          onChanged: (newVal) {
            _selectedPerson = newVal;
            setState(() {});
          });
      

      【讨论】:

        【解决方案8】:

        您将第一个城市硬编码为下拉列表的值。

        new DropdownButton(
                    value: cities.elementAt(0), //this one
        ...
        

        您需要有一些state 变量来保存所选城市。

        class YourStatefulWidgetState extends State<YourStatefulWidget> {
          @override
          initState() {
           super.initState();
           selectedCity = cities.elementAt(0)
          }
        
         @override
         Widget build(BuildContext context) {
           ...
           new DropdownButton(
                    value: selectedCity,
                    hint: new Text("Ville"),
                    items: cities.map((String value) {
                      return new DropdownMenuItem(value: value,
                        child: new Row(
                          children: <Widget>[
                            new Icon(
                              Icons.location_city, color: Colors.deepOrange,),
                            new Text(value)
                          ],
                        ),);
                    }).toList(),
                    onChanged: (String value) {
                      setState(() {
                        selectedCity = getTravelCity(value);
                      });
                    },),
             ...
        

        【讨论】:

        • 我忘了告诉你下拉菜单在 AlertDialog 中
        • @PondikpaTchabao 你有自己的对话框小部件吗?我认为此代码不适用于您的情况,因为 setState 调用正在更新构建对话框的小部件,而不是对话框。您应该创建自己的“DropdownAlertDialog”Stateful 小部件
        【解决方案9】:

        我厌倦了所有选项,包括所有颤振问题。 但是经过2个小时的搜索。我找到了我的 Bloc 实现小部件的解决方案。

         onChanged: (Object value) {
             selectedCity = getTravelCity(value);
             setState((){}; });
                );
        

        您可以在这里感受到不同。由于我在 BlocBuilder 下填充了某种状态的列表,因此它不允许您重建下拉菜单。因此,在设置 dropdownValue 之后,调用 setState 方法。它会让你体现价值。

        谢谢!

        【讨论】:

          猜你喜欢
          • 2019-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-08
          • 2016-12-04
          • 2020-01-24
          相关资源
          最近更新 更多