在颤动中单击按钮时添加小部件时处理动态复选框列表

Posted

技术标签:

【中文标题】在颤动中单击按钮时添加小部件时处理动态复选框列表【英文标题】:Handle the list of dynamic checkboxes when the widget is added on button click in flutter 【发布时间】:2021-01-14 09:32:23 【问题描述】:

单击添加按钮时,会复制相同的小部件。该小部件包含可多选的复选框列表。我能够复制小部件,但是根据小部件的索引处理复选框时遇到了问题。在下图中,复选框选中状态与新的添加小部件一起复制。

我已经实现如下:

根据添加按钮点击构建小部件

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

添加和删除小部件功能

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

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

我的回调函数

 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】:

这个问题是因为您通过countingwidget.responseMarket 控制所有副本。如果您希望所有副本单独工作,您需要实际复制它。

我建议创建一个新的 StatefulWidget 来替换 _buildSingleCheckBox() & _buildCheckBoxes() 函数。我还在里面放了showHidee

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

其次,除了counting对replica的控制之外,你应该使用一个List来存储responseMarket在原始类中的所有replica。

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],), 
  ...

最后,你要修改addRowdeleteRow函数。每次创建一个新的 ResponseMarkets 对象。

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

【讨论】:

在没有选择容器索引0并且添加容器时选择了复选框项时,但在选择容器索引0并添加容器时添加的复容器索引项时,请添加新容器值与索引 0 容器中的值一样。 我注意到我没有解决您的问题,因为原始副本由 countingwidget.responseMarket 控制(这是创建此对象的最终版本)。我修改它并更新代码。

以上是关于在颤动中单击按钮时添加小部件时处理动态复选框列表的主要内容,如果未能解决你的问题,请参考以下文章

PyQt 中的动态小部件添加

在颤动中动态地将小部件添加到列的子项

如何在颤动中的扩展磁贴内添加带有动态选择复选框的列表视图

Django - 修改Inlineformset删除按钮

如何在颤动中从类(小部件外部)打开屏幕

单击列表项时如何识别关联的小部件?