Handle the list of dynamic checkboxes when the widget is added on button click in flutter

强颜欢笑 提交于 2021-02-13 12:16:56

问题


When clicking the add button, the same widget is replicated. The widget contains the list of checkboxes that are multi selectable. I am able to replicate the widget but I got problem to handle the checkboxes according to the index of the widget. In image below the checkbox checked state is replicated along with the new add widget.

I have implemented as follows:

Build the widget according to the addbutton click

  ListView.builder(
                  itemCount: counting,
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemBuilder: (_, index) {
                    return _buildLayout(context, index);
                  });



                 //counting is number of **blueplus** icon is clicked
     Widget  _buildLayout(BuildContext context, int i) {       
      return Column(
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: <Widget>[
            Text(
              addContainer,
              style: TextStyle(color: Colors.blueGrey),
            ),
            Container(
              width: 64.0,
              alignment: Alignment.center,
              child: IconButton(
                  onPressed: () => {i == 0 ? addRow(i) : deleteRow(i)},
                  icon: Icon(
                    i == 0
                        ? Icons.add_circle_outline
                        : Icons.remove_circle_outline,
                    color: i == 0 ? Theme.of(context).primaryColor : Colors.red,
                  )),
            ),
          ],
        ),        
        _buildCheckBoxes()
      ],
    );
  }



Widget _buildCheckBoxes() {
    return
        Container(         
            width: MediaQuery.of(context).size.width,
            child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  InkWell(
                      onTap: () {
                        showHide();
                      },
                      child: Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: <Widget>[
                            Text(
                              productionmareketway,
                              style: TextStyle(
                                  fontSize: 18, fontWeight: FontWeight.bold),
                            ),
                            showHidee
                                ? Icon(Icons.keyboard_arrow_up)
                                : Icon(Icons.keyboard_arrow_down)
                          ])),
                  SizedBox(
                    width: 20,
                  ),
                  showHidee
                      ? ListView.builder(
                          shrinkWrap: true,
                          physics: const NeverScrollableScrollPhysics(),
                          itemCount: widget.responseMarket.length,
                          itemBuilder: (ctx, i) {
                            return _buildSingleCheckBox(
                                context,
                                widget.responseMarket[i].name,
                                widget.responseMarket[i].isChecked,
                                widget.responseMarket[i].id,
                                widget.responseMarket[i].identifier,
                                i);
                          })
                      : Container()
                ])
           );
          } 
  



Widget _buildSingleCheckBox(BuildContext context, String name, bool isChecked,
      int i, String identifier, int j) {
    return Container(
      child: new CheckboxListTile(
        title: new Text(name),
        value: isChecked,
        activeColor: Theme.of(context).primaryColor,
        checkColor: Colors.white,
        onChanged: (bool value) {
          setState(() {
            widget.responseMarket[i].isChecked = value;
            print(value);
            print(i);

            widget._onChecked(
                value,
                widget.responseMarket[i].id,
                widget.responseMarket[i].name,
                widget.responseMarket[i].identifier,
                counting);
          });
        
        },
      ),
    );
  }

Add and delete widget function

addRow(int i) {
setState(() {
  counting = counting + 1;
});
} 

 deleteRow(int i) {
    setState(() {
      counting = counting - 1;
    });
  }

My callback function

 onMarketChecked(var value, int i, String name, String identifier, int j) {
setState(() {
  if (responseMarket[i].isChecked == true) {
    nonMarketRepated.add(name);
  } else {
    nonMarketRepated.remove(responseMarket[i].name);
  }
});
}

回答1:


This issue is because you control all replica by counting and widget.responseMarket. If you want all replicas work individually, you need to Replica it actually.

I suggest to create a new StatefulWidget to replace _buildSingleCheckBox() & _buildCheckBoxes() function. I also put showHidee inside it.

class CheckBoxesWidget extends StatefulWidget {
  final responseMarket;

  CheckBoxesWidget({this.responseMarket, Key key}) : super(key: key);

  @override
  _CheckBoxesWidgetState createState() => _CheckBoxesWidgetState();
}

class _CheckBoxesWidgetState extends State<CheckBoxesWidget> {
  bool showHidee;

  @override
  void initState() {
    showHidee = true;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          InkWell(
            onTap: () {
              showHide();
            },
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text(
                  'productionmareketway',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                showHidee
                    ? Icon(Icons.keyboard_arrow_up)
                    : Icon(Icons.keyboard_arrow_down)
              ],
            ),
          ),
          SizedBox(
            width: 20,
          ),
          if (showHidee)
            Column(
              children: widget.responseMarket
                  .map(
                    (e) => CheckboxListTile(
                      title: Text(e.name),
                      value: e.isChecked,
                      activeColor: Theme.of(context).primaryColor,
                      checkColor: Colors.white,
                      onChanged: (bool value) {
                        setState(() {
                          e.isChecked = value;
                        });
                      },
                    ),
                  )
                  .toList(),
            ),
        ],
      ),
    );
  }

  void showHide() {
    setState(() {
      showHidee = !showHidee;
    });
  }
}

Second, beyond control the replica by counting, you should use a List to store all replica of responseMarket in the original class.

List<List<Market>> responseMarkets;

@override
void initState() {
  responseMarkets = [widget.responseMarket];
  super.initState();
}

...
@override
Widget build(BuildContext context) {
  return ListView.builder(
      itemCount: responseMarkets.length,
      itemBuilder: (_, index) {
        return _buildLayout(context, index);
      });
}

...
Widget _buildLayout(BuildContext context, int i) {
  ...
  // replace _buildCheckBoxes() with this line
  CheckBoxesWidget(responseMarket: responseMarkets[i],), 
  ...
}

Finally, you have to modify the addRow, deleteRow function. Each time create a new ResponseMarkets Object.

addRow(int i) {
  setState(() {
    responseMarkets.add(responseMarkets[0]
        .map((e) => ResponseMarkets(
              id: e.id,
              name: e.name,
              identifier: e.identifier,
              isChecked: e.isChecked,
            ))
        .toList());
  });
}

deleteRow(int i) {
  setState(() {
    responseMarkets.removeAt(i);
  });
}


来源:https://stackoverflow.com/questions/64108301/handle-the-list-of-dynamic-checkboxes-when-the-widget-is-added-on-button-click-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!