【问题标题】:Flutter/Dart: Handling Dropdown changes within a ListView.builder, Dropdown button not updating,Flutter/Dart:处理 ListView.builder 中的下拉更改,下拉按钮不更新,
【发布时间】:2019-05-07 18:14:22
【问题描述】:

我猜我遗漏了一些简单的东西,但我已经在这几天尝试了所有可能的解决方案。我们如何处理 listview.builder 中的下拉选择?是否可以将下拉按钮值存储在 List-String- 中?

我正在创建一个基于 XML 模板的动态表单,并具有下拉菜单、复选框、输入等。编辑: 在页面加载时解析 XML 之前,我不知道需要哪些小部件.因此尝试将动态创建的小部件列表传递给 Listview.builder。

下面的代码是一个未能更新的基本示例。

在这里感谢任何建议。

import 'package:flutter/material.dart';

class FormEG extends StatefulWidget {
  @override
  _FormEGState createState() => new _FormEGState();
}

class _FormEGState extends State<FormEG> {
  List<String> _listValues;
  List<DropdownMenuItem<String>> _items;
  List<Widget> _widgets;

  @override
  void initState() {
    _listValues = new List<String>();
    _listValues.add("b");

    _items = new List<DropdownMenuItem<String>>();
    _items.add(new DropdownMenuItem(child: Text("a"), value: "a"));
    _items.add(new DropdownMenuItem(child: Text("b"), value: "b"));
    _items.add(new DropdownMenuItem(child: Text("c"), value: "c"));
    _items.add(new DropdownMenuItem(child: Text("d"), value: "d"));

    _widgets = new List<Widget>();
    _widgets.add(new DropdownButton<String>(
      value: _listValues[0],
      items: _items,
      onChanged: (String newValue) {
        setState(() {
          _listValues[0] = newValue;
        });
      },
    ));
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        body: new ListView.builder(
          itemCount: _widgets.length,
          itemBuilder: (context, index) {
          return _widgets[index];
          },
        ));
      }
  }

【问题讨论】:

  • 您的 _widgets[0] 没有得到更新,它在每个 setState 上都有相同的按钮。 SetState() 再次调用 Build 方法并再次绘制 Button 但在您的情况下,您在 _widgets[index] 处分配了静态按钮。您必须在 Build Method 而不是 InitState 中移动 Widget 绘图方法。

标签: listview dart flutter dropdownbutton


【解决方案1】:

我最终用 statefulbuilder 包装了每个下拉小部件(在 List&lt;Widget&gt; 中),因此当从每个小部件调用 setstate 时,仅更新该小部件,但如果需要,仍然可以更新整个树。这样,根据 anmol.majhail cmets 从构建中调用 setState。

import 'package:flutter/material.dart';

class FormEG extends StatefulWidget {
  @override
  _FormEGState createState() => new _FormEGState();
}

class _FormEGState extends State<FormEG> {
  List<String> _listValues;
  List<DropdownMenuItem<String>> _items;
  List<Widget> _widgets;

  @override
  void initState() {
    _listValues = new List<String>();
    setDefaults();
    setWidgets();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print("built");
    return new Scaffold(
        body: new ListView.builder(
          itemCount: _widgets.length,
          itemBuilder: (context, index) {
        return _widgets[index];
      },
    ));
  }

  void setDefaults() {
    _listValues.add("b");
  }

  void setWidgets() {
    setMenuItems();
    _widgets = new List<Widget>();
    _widgets.add(
      new StatefulBuilder(
        builder: (BuildContext context, StateSetter setState) {
          return new DropdownButton<String>(
            value: _listValues[0],
            items: _items,
            onChanged: (String newValue) {
              setState(() {
                _listValues[0] = newValue;
              });
            },
          );
        },
      ),
    );
  }

  void setMenuItems() {
    _items = new List<DropdownMenuItem<String>>();
    _items.add(new DropdownMenuItem(child: Text("a"), value: "a"));
    _items.add(new DropdownMenuItem(child: Text("b"), value: "b"));
    _items.add(new DropdownMenuItem(child: Text("c"), value: "c"));
    _items.add(new DropdownMenuItem(child: Text("d"), value: "d"));
  }
}

【讨论】:

    【解决方案2】:

    以下代码运行良好。因为 SetSate 再次调用 Build 方法 & DropdownButton 再次被绘制。在您的代码中,DropdownButton 位于 _widgets[0] 值处,并且此值在整个代码周期中保持静态。即使在调用 SetState 之后,它也会保持不变 - 因为 SetState 不会更新 _widgets[0] 值 - 它只会再次调用 Build Method。

    @override
      Widget build(BuildContext context) {
        return new Scaffold(
            body: new ListView.builder(
          itemCount: _widgets.length,
          itemBuilder: (context, index) {
            return DropdownButton<String>(
              value: _listValues[0],
              items: _items,
              onChanged: (newValue) {
                setState(() {
                  _listValues[0] = newValue;
                });
              },
            );
          },
        ));
      }
    

    【讨论】:

    • 感谢 anmol.majhail。不幸的是,我的列表视图是基于 xml 文件的内容的动态的,所以在读取 xml 之前我不知道需要哪些小部件,因此无法将小部件硬编码到“构建”中。希望是根据 xml 内容动态创建一个小部件列表,然后将其提供给 listview.builder。我猜然后考虑到小部件 [0] 是静态的,这是不可能的,我需要每次都在设置状态下重新创建小部件列表。
    • 是 - 最初您可以根据 xml 内容动态创建小部件列表,然后将其提供给 listview.builder - 但是为了显示屏幕 UI 或小部件中的更改,您需要提供小部件列表新值或更新已构建列表中的值。
    • 而为小部件列表提供新值/更新的唯一方法是重新生成列表并重建整个树?!?
    • setState 执行相同的工作,但用于构建方法,但在您的情况下,小部件位于列表中,因此您需要手动更新列表值。
    【解决方案3】:

    您可以尝试只使用列表并动态更新列表,然后设置状态。

    ListView(
                      shrinkWrap: true,
                      scrollDirection: Axis.vertical,
                      children: dropDownList),
                ),
    

    然后根据触发器/事件更新它。

     _buildDropDownList() {
         if (dropDownEnabled) {
           setState (() {
             dropDownList.addAll([1,2,,4,5])
           });
           } else {
            setState (() {
             dropDownList = [];
          });   
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-27
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多