chk.buddi
chk.buddi

Reputation: 603

How to add delete function to remove dynamically generated widget in flutter

In my flutter app, I have implemented an image picker from the gallery and reordering. Now I want to implement 'delete' function when the user tap on each image displayed on the screen. So, I simply used 'removeAt(index)' but it always delete higest index image in the list as all images keep their index position as the length of the array of images. Can anybody help me with how to implement the delete function properly?

This is the code :

  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),
                                        ],
                                      ),
                                    ),
                                  )),
                            ],
                          )),
                    ),
                  ),
                ),
              ],
            ),
          ),

Upvotes: 0

Views: 949

Answers (1)

Maurice Raguse
Maurice Raguse

Reputation: 4567

convert your foreach loop to a for loop with index

for (XFile img in _imageList!) { ...}

to

for (int index=0; _imageList.length; index++)   

now you have an index for your remove call

_tiles.removeAt(index);

Upvotes: 1

Related Questions