在屏幕外滚动项目时,Flutter ListView小部件会重置图标

时间:2019-06-05 07:12:43

标签: flutter flutter-layout

我有一个ListView带有自定义的statefull小部件作为项目。 这些项目都有一个onTap事件,可以将图标从check_box_outline_blank切换到check_box,反之亦然。

但是,当我在列表中选择一个项目并向下滚动并再次备份时,该项目已将图标从check_box重置为check_box_outline_blank。

如何防止这种情况发生?

            new Expanded(
                child: ListView.builder(
                  itemCount: _list.length,
                  itemBuilder: (BuildContext context, int index) {
                    return listTile(_pveList[index], index)
                  },
                )
            )

 //Adds extra space(height:100) after the last tile
 StatefulWidget listTile(String text, int index){
    return (index < _pveList.length - 1)?new SelectableListItem(text: text,
      onTap: (){
        _handleOnTap(text);
      },
    ): new Column(
      children: <Widget>[
        new SelectableListItem(text: text,
          onTap: (){
            _handleOnTap(text);
          },
        ),
        SizedBox(
          height: 100,
        )
      ],
    );
  }

磁贴窗口小部件( SelectableListItem ):

import 'package:flutter/material.dart';

class SelectableListItem extends StatefulWidget {
  SelectableListItem({Key key, this.text, this.onTap})
      : super(key: key);
  final String text;
  final GestureTapCallback onTap;

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

class _SelectableListItemState extends State<SelectableListItem> {

  bool isSelected = false;
  Icon _checked = new Icon(Icons.check_box_outline_blank);

  handleOnTap() {
    isSelected = !isSelected;
    if (isSelected) {
      setState(() {
        _checked = new Icon(Icons.check_box);
      });
    } else {
      setState(() {
        _checked = new Icon(Icons.check_box_outline_blank);
      });
    }
    return widget.onTap();
  }

  @override
  Widget build(context) {
    // Pass the text down to another widget
    return new GestureDetector(
      behavior: HitTestBehavior.translucent,
      onTap: () => handleOnTap(),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          new Padding(
            padding: EdgeInsets.all(22),
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                new Text(widget.text, style: TextStyle(fontSize: 18)),
                _checked
              ],
            ),
          ),
          new Container(
            width: double.infinity,
            height: 1,
            color: Color(0x1a222222),
          )
        ],
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

已更新

我相信OP希望实现一个带有标签文本的标准Checkbox。

CheckboxListTile小部件提供了这种功能。

用法示例:

bool selected = false;

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Column(children: <Widget>[

      CheckboxListTile(
        onChanged: (val) {
          setState(() {
            selected = !selected;
          });
        },
        value: selected,
        title: Text("Test"),
      )

    ]),
  );
}

如果您希望复选框位于屏幕左侧,请相应设置controlAffinity属性:

CheckboxListTile(
  // ...,
  controlAffinity: ListTileControlAffinity.leading,
)

原始答案

#1

永远不要使用函数来构建小部件树。

有关更多详细信息,请参见this answer

#2

我建议使用ValueNotifier类中声明的SelectableListItem

它使您可以更改StatefulWidget中变量的值,而无需通常警告非最终变量。

ValueNotifier内的值也被保留,就像StatefulWidget类中声明的任何其他变量一样。

例如

class SelectableListItem extends StatefulWidget {
  // ...
  final ValueNotifier<bool> isSelected = ValueNotifier<bool>(false);
  // ...
}

class _SelectableListItemState extends State<SelectableListItem> {

  handleOnTap() {
    setState(() {
      widget.isSelected.value = !widget.isSelected.value;
    });
    return widget.onTap();
  }

  // ... build() { ...
  Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
      Text(widget.text, style: TextStyle(fontSize: 18)),
      Icon(widget.isSelected.value ? Icons.check_box : Icons.check_box_outline_blank),
    ]
  ),
  // ... } ...

}

ValueNotifier<bool>还消除了将图标小部件存储在单独变量中的需要。相反,您可以在内联布尔条件下使用它,就像代码中显示的一样。

PS:我没有测试代码,但是一般说明仍然有效。让我知道是否有帮助。