我有一个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),
)
],
),
);
}
}
答案 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,
)
永远不要使用函数来构建小部件树。
有关更多详细信息,请参见this answer。
我建议使用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:我没有测试代码,但是一般说明仍然有效。让我知道是否有帮助。