Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
684 views
in Technique[技术] by (71.8m points)

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

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.

enter image description here

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);
  }
});
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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);
  });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...