如何添加删除功能以在颤动中删除动态生成的小部件

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);