如何删除特定索引中 ListView 中的小部件?
How can i remove a widget in a ListView in a specific index?
我已经搜索了几个小时,但没有结果。我有一个用这个构造函数构建的 ListView
ListView.builder(
itemCount: 5,
itemBuilder: (context, int index) {
return ServiceCard(index: index,);
},
),
现在,在 ServiceCard 小部件中,我有一个按钮可以删除 ListView 树中的当前小部件,例如第 3 个 ServiceCard 小部件。
试了很多方法都不行。令我惊讶的是,即使是 flutter 文档也没有说明如何实现这种通用功能。
我试过给 ListView 一个变量,这样我就可以访问它并从中删除所需的小部件。不幸的是没有这样的功能。
我已经尝试为 ListView 提供一个准备好的 ServiceCard 小部件列表,然后我将其用于 ListView 的 itemCounter。然后从指定 ServiceCard 小部件上按钮的 setState 中的列表中删除一个项目。
我尝试使用一种方法,该方法将索引作为参数,并且 returns ServiceCard 仅在当前索引等于已删除项目的索引的情况下使用。不幸的是,这删除了最后一张不是指定的服务卡。
这是 ServiceCard 小部件:
class ServiceCard extends StatefulWidget {
ServiceCard({this.index});
int index;
@override
_ServiceCardState createState() => _ServiceCardState();
}
class _ServiceCardState extends State<ServiceCard> {
void onFormSubmitted() {
var form = formKey.currentState;
if (form.validate()) {
form.save();
}
}
@override
Widget build(BuildContext context) {
int index = widget.index;
return Container(
height: 440,
child: Column(
children: <Widget>[
ExpandableRoundRectangleContainer(
widgetList: <Widget>[
Container(
height: 370,
child: Stack(
alignment: Alignment.bottomLeft,
children: <Widget>[
//column for tow TextField with headers
Column(
children: <Widget>[
HeaderTextWithFormTextFieldAndSizedBox(
headerText: 'Service Name',
hintText: 'Write your service name here...',
autoFocus: true,
iconData: Icons.info_outline,
validatorFunction: (String value) {
if (value.length > 0 && value.length < 6) {
return '*Service name should be more than 5 letters';
} else if (value.length == 0) {
return '* Service name is required';
}
},
onSaved: (String value) {},
),
HeaderTextWithFormTextFieldAndSizedBox(
headerText: 'Service Description',
hintText: 'Write your service description here...',
autoFocus: false,
iconData: Icons.info_outline,
validatorFunction: (String value) {
if (value.length > 0 && value.length < 6) {
return '* Service description should be more than 5 letters';
} else if (value.length == 0) {
return '* Service description is required';
}
},
letterCount: 200,
maxLines: 3,
contentPadding: 13,
onSaved: (String value) {},
),
],
),
//only add the add service button when it is the last card
Visibility(
// visible: widget.index == serviceNamesList.length - 1 ,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RoundButtonWithIconFix(
text: 'Add Another Service',
buttonWidth: 160,
buttonColor: kAppLightBlueColor,
onButtonPressed: () {},
icon: Icons.add_box,
color: Colors.white,
iconTextSpacing: 5,
iconSize: 25,
),
),
),
Positioned(
bottom: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RoundButtonWithIconFix(
text: 'Remove Service',
buttonWidth: 130,
buttonColor: kAppLightBlueColor,
onButtonPressed: () {
setState(() {
});
},
icon: Icons.delete,
color: Colors.white,
iconTextSpacing: 5,
iconSize: 25,
),
),
),
],
),
),
],
),
Visibility(
// visible: widget.index == serviceNamesList.length - 1 ,
child: DoneButton(
onPressed: onFormSubmitted,
),
),
],
),
);
}
}
您可以创建一个列表并将其传递给您的 ListView 并使用 remove
函数删除实际对象并调用 setState((){})
刷新您的 UI.
这是一个示例,您可以 运行:
class StreamBuilderIssue extends StatefulWidget {
@override
_StreamBuilderIssueState createState() => _StreamBuilderIssueState();
}
class _StreamBuilderIssueState extends State<StreamBuilderIssue> {
List<ServiceCard> serviceCardList;
void removeServiceCard(index) {
setState(() {
serviceCardList.remove(index);
});
}
@override
void initState() {
super.initState();
serviceCardList = List.generate(
5, (index) => ServiceCard(removeServiceCard, index: index));
}
@override
Widget build(BuildContext context) {
print('build + ${serviceCardList.length}');
return Scaffold(
body: ListView(
children: <Widget>[...serviceCardList],
),
);
}
}
class ServiceCard extends StatelessWidget {
final int index;
final Function(ServiceCard) removeServiceCard;
const ServiceCard(this.removeServiceCard, {Key key, @required this.index})
: super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(
'Index: ${index.toString()} Hashcode: ${this.hashCode.toString()}'),
RaisedButton(
color: Colors.accents.elementAt(3 * index),
onPressed: () {
removeServiceCard(this);
},
child: Text('Delete me'),
),
],
);
}
}
这是显示其行为的 gif external link
我正在显示索引和哈希码以表明它确实是被删除的所需对象
我已经搜索了几个小时,但没有结果。我有一个用这个构造函数构建的 ListView
ListView.builder(
itemCount: 5,
itemBuilder: (context, int index) {
return ServiceCard(index: index,);
},
),
现在,在 ServiceCard 小部件中,我有一个按钮可以删除 ListView 树中的当前小部件,例如第 3 个 ServiceCard 小部件。
试了很多方法都不行。令我惊讶的是,即使是 flutter 文档也没有说明如何实现这种通用功能。
我试过给 ListView 一个变量,这样我就可以访问它并从中删除所需的小部件。不幸的是没有这样的功能。
我已经尝试为 ListView 提供一个准备好的 ServiceCard 小部件列表,然后我将其用于 ListView 的 itemCounter。然后从指定 ServiceCard 小部件上按钮的 setState 中的列表中删除一个项目。
我尝试使用一种方法,该方法将索引作为参数,并且 returns ServiceCard 仅在当前索引等于已删除项目的索引的情况下使用。不幸的是,这删除了最后一张不是指定的服务卡。
这是 ServiceCard 小部件:
class ServiceCard extends StatefulWidget {
ServiceCard({this.index});
int index;
@override
_ServiceCardState createState() => _ServiceCardState();
}
class _ServiceCardState extends State<ServiceCard> {
void onFormSubmitted() {
var form = formKey.currentState;
if (form.validate()) {
form.save();
}
}
@override
Widget build(BuildContext context) {
int index = widget.index;
return Container(
height: 440,
child: Column(
children: <Widget>[
ExpandableRoundRectangleContainer(
widgetList: <Widget>[
Container(
height: 370,
child: Stack(
alignment: Alignment.bottomLeft,
children: <Widget>[
//column for tow TextField with headers
Column(
children: <Widget>[
HeaderTextWithFormTextFieldAndSizedBox(
headerText: 'Service Name',
hintText: 'Write your service name here...',
autoFocus: true,
iconData: Icons.info_outline,
validatorFunction: (String value) {
if (value.length > 0 && value.length < 6) {
return '*Service name should be more than 5 letters';
} else if (value.length == 0) {
return '* Service name is required';
}
},
onSaved: (String value) {},
),
HeaderTextWithFormTextFieldAndSizedBox(
headerText: 'Service Description',
hintText: 'Write your service description here...',
autoFocus: false,
iconData: Icons.info_outline,
validatorFunction: (String value) {
if (value.length > 0 && value.length < 6) {
return '* Service description should be more than 5 letters';
} else if (value.length == 0) {
return '* Service description is required';
}
},
letterCount: 200,
maxLines: 3,
contentPadding: 13,
onSaved: (String value) {},
),
],
),
//only add the add service button when it is the last card
Visibility(
// visible: widget.index == serviceNamesList.length - 1 ,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RoundButtonWithIconFix(
text: 'Add Another Service',
buttonWidth: 160,
buttonColor: kAppLightBlueColor,
onButtonPressed: () {},
icon: Icons.add_box,
color: Colors.white,
iconTextSpacing: 5,
iconSize: 25,
),
),
),
Positioned(
bottom: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RoundButtonWithIconFix(
text: 'Remove Service',
buttonWidth: 130,
buttonColor: kAppLightBlueColor,
onButtonPressed: () {
setState(() {
});
},
icon: Icons.delete,
color: Colors.white,
iconTextSpacing: 5,
iconSize: 25,
),
),
),
],
),
),
],
),
Visibility(
// visible: widget.index == serviceNamesList.length - 1 ,
child: DoneButton(
onPressed: onFormSubmitted,
),
),
],
),
);
}
}
您可以创建一个列表并将其传递给您的 ListView 并使用 remove
函数删除实际对象并调用 setState((){})
刷新您的 UI.
这是一个示例,您可以 运行:
class StreamBuilderIssue extends StatefulWidget {
@override
_StreamBuilderIssueState createState() => _StreamBuilderIssueState();
}
class _StreamBuilderIssueState extends State<StreamBuilderIssue> {
List<ServiceCard> serviceCardList;
void removeServiceCard(index) {
setState(() {
serviceCardList.remove(index);
});
}
@override
void initState() {
super.initState();
serviceCardList = List.generate(
5, (index) => ServiceCard(removeServiceCard, index: index));
}
@override
Widget build(BuildContext context) {
print('build + ${serviceCardList.length}');
return Scaffold(
body: ListView(
children: <Widget>[...serviceCardList],
),
);
}
}
class ServiceCard extends StatelessWidget {
final int index;
final Function(ServiceCard) removeServiceCard;
const ServiceCard(this.removeServiceCard, {Key key, @required this.index})
: super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(
'Index: ${index.toString()} Hashcode: ${this.hashCode.toString()}'),
RaisedButton(
color: Colors.accents.elementAt(3 * index),
onPressed: () {
removeServiceCard(this);
},
child: Text('Delete me'),
),
],
);
}
}
这是显示其行为的 gif external link
我正在显示索引和哈希码以表明它确实是被删除的所需对象