如何添加删除功能以在颤动中删除动态生成的小部件
How to add delete function to remove dynamically generated widget in flutter
在我的 flutter 应用程序中,我实现了一个从图库中选择图像并重新排序的功能。现在我想在用户点击屏幕上显示的每个图像时实现 'delete' 功能。所以,我简单地使用了 'removeAt(index)' 但它总是删除列表中最高的索引图像,因为所有图像都将它们的索引位置保持为图像数组的长度。谁能帮我正确实现删除功能?
这是代码:
final List<XFile>? _imageList = [];
final imagePicker = ImagePicker();
final Logger log = LoggerService.logger('ImageUpload');
FirebaseDao firebasDao = locator.get<FirebaseDao>();
late final Map<String, dynamic> _newImgList = <String, dynamic>{};
int i = 0;
late List<Widget> _tiles;
Future pickImage() async {
final List<XFile>? pick = await imagePicker.pickMultiImage(
maxWidth: 640, maxHeight: 480, imageQuality: 50);
setState(() {
if (pick != null) {
_imageList!.clear();
_imageList!.addAll(pick);
for (XFile img in _imageList!) {
_tiles.add(Container(
child: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
setState(() {
_tiles.removeAt(i);
});
},
),
height: 50,
width: 50,
margin: const EdgeInsets.all(3),
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.scaleDown, image: FileImage(File(img.path))),
),
));
_newImgList.putIfAbsent(i.toString(), () => img);
i++;
}
} else {
showSnackBar(
context, 'No image selected', const Duration(microseconds: 1000));
}
});
}
Future uploadImage() async {
Reference ref;
int count = 0;
int postId = DateTime.now().microsecondsSinceEpoch;
for (var key in _newImgList.keys) {
count++;
postId = postId + count;
ref = FirebaseStorage.instance
.ref()
.child('${firebasDao.getCurrentUser()!.uid}/posts')
.child(postId.toString());
await ref.putFile(File(_newImgList[key].path)).whenComplete(() async {
var url = await ref.getDownloadURL();
_newImgList.update(key, (value) => url);
});
}
}
showSnackBar(BuildContext context, String snackBarText, Duration d) {
final snackBar = SnackBar(content: Text(snackBarText), duration: d);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
@override
void initState() {
super.initState();
_tiles = <Widget>[
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
pickImage();
},
)
];
}
@override
Widget build(BuildContext context) {
void _onReorder(int oldIndex, int newIndex) {
setState(() {
Widget row = _tiles.removeAt(oldIndex);
_tiles.insert(newIndex, row);
var temp = _newImgList[(newIndex - 1).toString()];
_newImgList.update((newIndex - 1).toString(),
(value) => _newImgList[(oldIndex - 1).toString()]);
_newImgList.update((oldIndex - 1).toString(), (value) => temp);
});
}
var wrap = ReorderableWrap(
spacing: 8.0,
runSpacing: 4.0,
padding: const EdgeInsets.all(8),
children: _tiles,
onReorder: _onReorder);
var _imageGrid = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[wrap],
);
return Form(
key: _addItemFormKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
left: 8.0,
right: 8.0,
bottom: 24.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(30.0)),
child: SizedBox(
height: 150,
width: double.infinity,
child: Column(
children: [
const SizedBox(
height: 10,
),
Expanded(
flex: 4,
child: SizedBox(
width: 400,
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(child: _imageGrid),
],
),
),
)),
],
)),
),
),
),
],
),
),
将 foreach 循环转换为带索引的 for 循环
for (XFile img in _imageList!) { ...}
至
for (int index=0; _imageList.length; index++)
现在您有一个用于删除调用的索引
_tiles.removeAt(index);
在我的 flutter 应用程序中,我实现了一个从图库中选择图像并重新排序的功能。现在我想在用户点击屏幕上显示的每个图像时实现 'delete' 功能。所以,我简单地使用了 'removeAt(index)' 但它总是删除列表中最高的索引图像,因为所有图像都将它们的索引位置保持为图像数组的长度。谁能帮我正确实现删除功能?
这是代码:
final List<XFile>? _imageList = [];
final imagePicker = ImagePicker();
final Logger log = LoggerService.logger('ImageUpload');
FirebaseDao firebasDao = locator.get<FirebaseDao>();
late final Map<String, dynamic> _newImgList = <String, dynamic>{};
int i = 0;
late List<Widget> _tiles;
Future pickImage() async {
final List<XFile>? pick = await imagePicker.pickMultiImage(
maxWidth: 640, maxHeight: 480, imageQuality: 50);
setState(() {
if (pick != null) {
_imageList!.clear();
_imageList!.addAll(pick);
for (XFile img in _imageList!) {
_tiles.add(Container(
child: IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
setState(() {
_tiles.removeAt(i);
});
},
),
height: 50,
width: 50,
margin: const EdgeInsets.all(3),
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.scaleDown, image: FileImage(File(img.path))),
),
));
_newImgList.putIfAbsent(i.toString(), () => img);
i++;
}
} else {
showSnackBar(
context, 'No image selected', const Duration(microseconds: 1000));
}
});
}
Future uploadImage() async {
Reference ref;
int count = 0;
int postId = DateTime.now().microsecondsSinceEpoch;
for (var key in _newImgList.keys) {
count++;
postId = postId + count;
ref = FirebaseStorage.instance
.ref()
.child('${firebasDao.getCurrentUser()!.uid}/posts')
.child(postId.toString());
await ref.putFile(File(_newImgList[key].path)).whenComplete(() async {
var url = await ref.getDownloadURL();
_newImgList.update(key, (value) => url);
});
}
}
showSnackBar(BuildContext context, String snackBarText, Duration d) {
final snackBar = SnackBar(content: Text(snackBarText), duration: d);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
@override
void initState() {
super.initState();
_tiles = <Widget>[
IconButton(
icon: const Icon(Icons.add),
onPressed: () {
pickImage();
},
)
];
}
@override
Widget build(BuildContext context) {
void _onReorder(int oldIndex, int newIndex) {
setState(() {
Widget row = _tiles.removeAt(oldIndex);
_tiles.insert(newIndex, row);
var temp = _newImgList[(newIndex - 1).toString()];
_newImgList.update((newIndex - 1).toString(),
(value) => _newImgList[(oldIndex - 1).toString()]);
_newImgList.update((oldIndex - 1).toString(), (value) => temp);
});
}
var wrap = ReorderableWrap(
spacing: 8.0,
runSpacing: 4.0,
padding: const EdgeInsets.all(8),
children: _tiles,
onReorder: _onReorder);
var _imageGrid = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[wrap],
);
return Form(
key: _addItemFormKey,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(
left: 8.0,
right: 8.0,
bottom: 24.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(30.0)),
child: SizedBox(
height: 150,
width: double.infinity,
child: Column(
children: [
const SizedBox(
height: 10,
),
Expanded(
flex: 4,
child: SizedBox(
width: 400,
child: Center(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(child: _imageGrid),
],
),
),
)),
],
)),
),
),
),
],
),
),
将 foreach 循环转换为带索引的 for 循环
for (XFile img in _imageList!) { ...}
至
for (int index=0; _imageList.length; index++)
现在您有一个用于删除调用的索引
_tiles.removeAt(index);