简体   繁体   中英

Drop down inside ListView in flutter

I have DropDownButton in ListView.Builder whenever I selected from dropdown it gives on change value but doesn't reflect on UI.

 List _warranty = ["NONE","1 YEAR", "2 YEAR"];
 List<DropdownMenuItem<String>> getDropDownWarranty() {
      List<DropdownMenuItem<String>> items = new List();
      for (String str in _warranty) {
        items.add(new DropdownMenuItem(
            value: str,
            child: new Text(
              str,
              style: TextStyle(color: Colors.white, fontFamily: 'semibold'),
            )));
      }
      return items;
    }

This is my ListView Item widget

  Widget item(AsyncSnapshot<CartBean> snapshot, int index) {
      String _current = "";
      return Column(
        children: <Widget>[
          Container(
            height: 40,
            decoration: BoxDecoration(color: MyColors.cartback),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.end,
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Container(
                  width: SizeConfig.screenWidth / 1.7,
                  padding: EdgeInsets.all(SizeConfig.blockSizeHorizontal * 2),
                  decoration: BoxDecoration(
                    color: MyColors.colorLightPrimary,
                  ),
                  child: snapshot.data.data[index].lcwInfo.length > 0
                      ? Theme(
                    data: Theme.of(context).copyWith(
                        brightness: Brightness.dark,
                        canvasColor: MyColors.colorPrimary),

                    child: dropDown(snapshot.data.data[index].lcwInfo,
                        _current,index), // Your Dropdown Code Here,
                  )
                      : FlatButton(
                    onPressed: () {},
                    padding: EdgeInsets.all(0),
                    child: Text(
                      "EXTEND WARRANTY",
                      style: TextStyle(
                          color: Colors.grey[300],
                          fontFamily: "semibold"),
                    ),
                  ),
                ),
                FlatButton.icon(
                  onPressed: () {
                    removeCartItemService(
                        snapshot.data.data[index].productId, index);
                  },
                  icon: Image.asset(
                    'assets/icons/cancel.png',
                    width: 28,
                    height: 28,
                  ),
                  label: Text(''),
                )
              ],
            ),
          ),
        ],
      );
    }

This method is calling in ListView Item widget

 Widget dropDown(List<LcwInfo> list, String _current,int index) {
      List<DropdownMenuItem<String>> _dropDownWarranty;
      _dropDownWarranty = getDropDownWarranty();
      _current = _dropDownWarranty[0].value;

      if (list.length > 0) {
        return DropdownButtonHideUnderline(
          child: DropdownButton<String>(
            value: _dropDownWarranty[0].value,
            items: _dropDownWarranty,
            onChanged: (String onValue) {
              debugPrint("CURRENT VALUE:----------${onValue}");
              updateWarrantyService(index,onValue,list[0]);
              setState(() {
                _dropDownWarranty[0] = onValue as DropdownMenuItem<String>;
              });
            },
          ),
        );
      }
    }

All Above methods are declared inside build(BuildContext context)

在此处输入图像描述

If all of this is inside the build when you call setState this will reset the values including the variables.

In your case _dropDownWarranty = getDropDownWarranty(); is setting the value of _dropDownWarranty to getDropDownWarranty(); everytime you call setState regardless of what it is set to in the the onChanged.

I would recommend moving the _dropDownWarranty = getDropDownWarranty(); outside of the build but within the class still. In fact, I would recommend moving function outside of the build method but keeping them in the class as a rule otherwise they will rerun every time you call setState!

This example shows how to set the value but not having it inside the build method https://stackoverflow.com/a/54948635/4644407

I have created one variable with selectedItemValue to store selected value in DropdownButton , Before i set default value to None all item.

    class ListViewDemo extends StatefulWidget {
    @override
    State<StatefulWidget> createState() {
        return ListViewDemoState();
    }
    }

    class ListViewDemoState extends State<ListViewDemo> {
    List<String> selectedItemValue = List<String>();

    @override
    void initState() {
        // TODO: implement initState
        super.initState();
    }

    @override
    Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
            title: Text("ListView"),
            ),
            body: Column(
            children: <Widget>[
                Expanded(
                child: ListView.builder(
                    itemCount: 20,
                    itemExtent: 50.0,
                    itemBuilder: (BuildContext context, int index) {
                        for (int i = 0; i < 20; i++) {
                        selectedItemValue.add("NONE");
                        }
                        return DropdownButton(
                        value: selectedItemValue[index].toString(),
                        items: _dropDownItem(),
                        onChanged: (value) {
                            selectedItemValue[index] = value;
                            setState(() {});
                        },
                        hint: Text('Select Gender'),
                        );
                    }),
                )
            ],
            ));
    }
    }

    List<DropdownMenuItem<String>> _dropDownItem() {
    List<String> ddl = ["NONE", "1 YEAR", "2 YEAR"];
    return ddl
        .map((value) => DropdownMenuItem(
                value: value,
                child: Text(value),
            ))
        .toList();
    }

在此处输入图像描述

You can try using expansion tile for this which is provided by flutter it.

ExpansionTile(
    title: Text(artistData.artistName),
        children: [
               ListTile(
                    leading: Image(
                    image: NetworkImage(artistData.artworkUrl100),
                        ),
                    title: Text(artistData.collectionName),
                      subtitle: Text(artistData.description),
                    )
                  ],
               );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM