在我的应用中,我确实有一个列表,在该列表上已经实现了长按选择的this post of Raouf Rahiche。启用选择后,我确实有一个不同的appbar
,上面有一个IconButton
,应该禁用选择。但是我不知道该怎么做。
到现在,它还没有按照应有的方式工作。该行为显示在下面的视频中。
longpress-selection是一个StatefulWidget:
class _SelectableItems extends State<SelectableItems> {
bool isSelected = false;
GoogleMaterialColors googleMaterialColors = new GoogleMaterialColors();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new GestureDetector(
onLongPress: () {
setState(() {
isSelected = !isSelected;
});
widget.callback();
},
onTap: () {
setState(() {
isSelected = !isSelected;
});
if (widget.longPressEnabled) {
widget.callback();
} else {
Navigator.push(
context,
MaterialPageRoute(builder: (context)=>RecipeDetails(widget.name))
);
}
},
child: ListTile(
leading: CircleAvatar(
child: (isSelected
? Icon(
Icons.check,
color: Colors.white,
)
: (widget.image != "no image"
? Container(
width: 40.0,
height: 40.0,
decoration: new BoxDecoration(
image: new DecorationImage(
colorFilter: ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: AssetImage(widget.image),
fit: BoxFit.cover,
),
borderRadius: new BorderRadius.all(new Radius.circular(50.0)),
),
)
: Text(
widget.name[0].toUpperCase(),
style: TextStyle(
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.w400
),
)
)
),
backgroundColor: (isSelected
? googleMaterialColors.primaryColor()
: widget.color.withOpacity(1.00)
)
),
title: Padding(
padding: EdgeInsets.only(top: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
widget.title
],
),
),
),
);
}
}
我在SideHeaderListView内这样调用此小部件:
bool longPressFlag = false;
List<String> indexList = new List();
//other code
return SideHeaderListView(
hasSameHeader: (int a, int b){
return snapshot.data[a].name[0] == snapshot.data[b].name[0];
},
itemCount: snapshot.data.length,
headerBuilder: (BuildContext context, int index){
return new Padding(
padding: EdgeInsets.only(top: 30.0, left: 20.0, right: 25.0),
child: Container(
width: 10.0,
child: Text(
snapshot.data[index].name[0].toUpperCase(),
style: TextStyle(
color: googleMaterialColors.primaryColor().withGreen(120),
fontFamily: "Google-Sans",
fontSize: 15.0,
fontWeight: FontWeight.w600
),
),
),
);
},
itemExtend: 70.0,
itemBuilder: (BuildContext context, int index){
Color usedColor = convertColor.convertToColor(snapshot.data[index].backgroundColor);
String image = snapshot.data[index].image;
return SelectableItems(
color: usedColor,
name: snapshot.data[index].name,
title: (searchController.text.isEmpty
? Text(snapshot.data[index].name)
: recipeName(searchCondition, snapshot.data[index].name)
),
index: index,
image: image,
longPressEnabled: longPressFlag,
//isSelected: selectedFlag,
callback: () {
if (indexList.contains(snapshot.data[index].name)) {
indexList.remove(snapshot.data[index].name);
} else {
indexList.add(snapshot.data[index].name);
}
longPress();
},
);
},
);
void longPress() {
setState(() {
if (indexList.length == 0) {
longPressFlag = false;
} else {
longPressFlag = true;
}
});
}
我希望有人能够解决我的问题。预先感谢。
答案 0 :(得分:0)
第一件事是,您应该像这样在构造函数中为每个项目添加一个键:
MyItem({Key key}): super(key: key);
为什么要钥匙? 按键可让您正确识别小部件。 参见文档:
新的窗口小部件将仅用于更新现有元素,如果其 键与与该控件关联的当前窗口小部件的键相同 元件。
创建一个GlobalKey(一个GLobal键扩展了Key) 对于从中访问小部件的每个项目,请创建一个全局密钥。 从文档中:
整个应用程序中唯一的键。全局密钥唯一 识别元素。全局键提供对其他对象的访问, 与元素相关联,例如[BuildContext]和 [StatefulWidget] s,一个[State]。
在代码中为每个项目(在您的SelectableItem中为您)创建一个全局密钥:
...
var key = new GlobalKey<SelectableItem >();
this.items.put(position, key);
return new SelectableItem(key: key,...);
Items是一张地图,您可以在其中保存位置和全局密钥。 现在,当您想从父级中选择一个视图时,只需从项目地图中访问globalKey并访问该小部件即可执行您想要的操作(更新,取消选中等...)
编辑:例如:
class SideHeaderListView {
Map<int, GlobalKey<_SelectableItems>> map = new Map();
create() {
for (int i = 0; i< 10; i++) {
var key = new GlobalKey<_SelectableItems>();
var item = new SelectableItems(key: key);
map.putIfAbsent(i, () => key);
}
}
redrawItem(int i) {
var widget = this.map[i].currentState;
widget.redraw();
}
}
class SelectableItems extends StatefulWidget {
SelectableItems({key: Key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return new _SelectableItems();
}
}
class _SelectableItems extends State<SelectableItems> {
@override
Widget build(BuildContext context) {
return new Text("test");
}
redraw() {
setState(() {
});
}
}
答案 1 :(得分:0)
您已注释了部分代码-//isSelected: selectedFlag,
我认为,您必须将此字段添加到小部件中
class SelectableItems extands StatefulWidget {
SelectableItems({this.isSelected = false});
final bool isSelected;
...
class _SelectableItems extends State<SelectableItems> {
bool isSelected;
@override
void initState() {
isSelected = widget.isSelected ?? false;
super.initState();
}
....
在创建项目列表时:
return SelectableItems(
...
isSelected: indexList.contains(snapshot.data[index].name)
我认为这可能有效