Flutter- Image picker package: show images one after another with delete action
Asked Answered
A

1

0

In my Flutter pr project, I am using Image Picker plugin to select images from the android mobile gallery or capture images with the camera and show them one after another with a delete icon below each image. On tapping the RaisedButton for selecting images from the gallery, the method imageSelectorGallery() is called. There inside the setState() method , I add a SizedBox and a delete icon to the List namely images_captured. I expect the images_captured to be rendered inside the Column in SingleChildScrollView.

But after selecting an image from the gallery, nothing happens. I also want to tap on the delete icon and remove the image above it. But flutter has no data binding mechanism as I know to correlate the image with the delete button.

Code follows:

class PrescriptionScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new UserOptionsState();
  }
}

class UserOptionsState extends State<PrescriptionScreen> {
//save the result of gallery fileUserOptions
  File galleryFile;

//save the result of camera file
  File cameraFile;

  @override
  Widget build(BuildContext context) {

    var images_captured=List<Widget>();


    //display image selected from gallery
    imageSelectorGallery() async {
      galleryFile = await ImagePicker.pickImage(
        source: ImageSource.gallery,
        // maxHeight: 50.0,
        // maxWidth: 50.0,
      );
      print("You selected gallery image : " + galleryFile.path);
      setState(() {



        var sized_box_indiv= new SizedBox(
            height: 200.0,
            width: 300.0,
//child: new Card(child: new Text(''+galleryFile.toString())),
//child: new Image.file(galleryFile),
            child:  galleryFile == null
                ? new Text('Sorry nothing selected from gallery!!')
                : new Image.file(galleryFile),

        );
        images_captured.add(sized_box_indiv);

        var delete_button = IconButton(icon: Icon(Icons.delete), onPressed: () {});
        images_captured.add(delete_button);

      });
    }

    //display image selected from camera
    imageSelectorCamera() async {
      cameraFile = await ImagePicker.pickImage(
        source: ImageSource.camera,
        //maxHeight: 50.0,
        //maxWidth: 50.0,
      );
      print("You selected camera image : " + cameraFile.path);
      setState(() {});
    }

 
          return new SingleChildScrollView(
              child:Column(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              new RaisedButton(
                child: new Text('Select Image from Gallery'),
                onPressed: imageSelectorGallery,
              ),
              new RaisedButton(
                child: new Text('Select Image from Camera'),
                onPressed: imageSelectorCamera,
              ),

              Column(
                          children: images_captured
                      ),

              
            ],
          ),
    );
       /* },
      ),
    );*/
  }


}

How to show the images selected from gallery one after another with a delete icon button below each of them?

How to remove the corresponding image on tapping the delete icon button?

I think if I can accomplish it for gallery, I can do it for camera capturing as well.

I used the answer by jJuice and the images after being selected showed overflow error. The screenshot is given below:

My code is:

class UserOptionsState extends State<PrescriptionScreen> {
//save the result of gallery fileUserOptions
  File galleryFile;

//save the result of camera file
  File cameraFile;
  var images_captured=List<Widget>();

  List<File> images = List<File>();

  @override
  Widget build(BuildContext context) {

    //display image selected from gallery
    imageSelectorGallery() async {



   galleryFile = await ImagePicker.pickImage(
        source: ImageSource.gallery,
        // maxHeight: 50.0,
        // maxWidth: 50.0,
      );

      images.add(galleryFile);
      print("You selected gallery image : " + galleryFile.path);
      setState(() {


        
      });
    }

    //display image selected from camera
    imageSelectorCamera() async {
      cameraFile = await ImagePicker.pickImage(
        source: ImageSource.camera,
        //maxHeight: 50.0,
        //maxWidth: 50.0,
      );
      print("You selected camera image : " + cameraFile.path);
      setState(() {});
    }



    return new SingleChildScrollView(
      child:Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          new RaisedButton(
            child: new Text('Select Image from Gallery'),
            onPressed: imageSelectorGallery,
          ),
          new RaisedButton(
            child: new Text('Select Image from Camera'),
            onPressed: imageSelectorCamera,
          ),

         new Container(
//            new Column(
//            children: <Widget>[
             height: 1200,
              child:GridView.count(
              crossAxisSpacing: 6,
              mainAxisSpacing: 6,
              crossAxisCount: 3,
              children: List.generate(images.length, (index) {
                return Column(
                    children: <Widget>[
                      Container(
                          height: 200,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                          ),
                          child: ClipRRect(
                            child: Image.file(images[index], fit: BoxFit.cover),
                            borderRadius: BorderRadius.circular(10),
                          )
                      ),
                      GestureDetector(
                        onTap: () {
                          setState(() {
                            images.removeAt(index);
                          });
                        },
                        child: Padding(
                          padding: const EdgeInsets.all(3.0),
                          child: Align(
                            alignment: Alignment.bottomCenter,
                            child: Icon(Icons.clear, color: Colors.black, size: 20),
                          ),
                        ),
                      ),
                    ]
                );
              }
              ),
            ),
//              ]
          )

          /*displaySelectedFile(galleryFile),
              displaySelectedFile(cameraFile)*/
        ],
      ),
    );



  }

  Widget displaySelectedFile(File file) {
    return new SizedBox(
      height: 200.0,
      width: 300.0,
//child: new Card(child: new Text(''+galleryFile.toString())),
//child: new Image.file(galleryFile),
      child: file == null
          ? new Text('Sorry nothing selected!!')
          : new Image.file(file),
    );
  }
}
Angleworm answered 6/3, 2020 at 14:4 Comment(6)
You can use this plugin if you want to load multiple images pub.dev/packages/multi_image_picker. See if it works or you need more help on it.Handmedown
what is the problem with my approach?Angleworm
With your approach you can only have one camera and one gallery picture because you are using a single instance for each. You can show them using page view and for a single page you can use a stack having a delete icon on it.Handmedown
new images are being added to 'images_captured' list. Why wouldn't they show up then? Even not a single image shows up? Can you post an answer with your approach i.e: stack etc? how would the delete action take place?Angleworm
Your list of images is empty because it is in build function and Everytime you get an image you call setState function which again call build function and your image list get created again. Try putting the var images_captured=List<Widget>() outside build function you will get all images.Handmedown
how can I make the delete action? how to find the corresponding image and then remove it?Angleworm
A
2

Question 1: You first need to store the images picked by using ImagePicker (or MultiImagePicker plugin) in a collection. Here's an example on how to do that:

List<File> images = List<File>(); images.add(await ImagePicker.pickImage(source: ImageSource.gallery, imageQuality: 20););

When you want to show those images on the screen, you can use several different widgets, like ListView, GridView, Row, Column. Here's an example where I use a GridView:

child: Container(
        height: 1200,
        child: GridView.count(
          crossAxisSpacing: 6,
          mainAxisSpacing: 6,
          crossAxisCount: 3,
          children: List.generate(images.length, (index) {
              return Column(
                  children: <Widget>[
                    Container(
                      height: 200,
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(10),
                      ),
                      child: ClipRRect(
                        child: Image.file(images[index], fit: BoxFit.cover), 
                        borderRadius: BorderRadius.circular(10),
                      )
                    ),
                    GestureDetector(
                      onTap: () {
                        setState(() {
                          images.removeAt(index);
                        });
                      },
                      child: Padding(
                        padding: const EdgeInsets.all(3.0),
                        child: Align(
                          alignment: Alignment.bottomCenter,
                          child: Icon(Icons.clear, color: Colors.white, size: 20),
                        ),
                      ),
                    ),
                  ] 
                ),
            }
        ),
      ),

I think using a Stack widget works best in this case. A Stack can be used to show Widgets, layered on top of each other. So in this case, a widget showing the image, with a Icon widget on top of it that is the button for your delete action.

Question 2: You could delete the image by calling the removeAt method available on collections like a List. See the code inside the onTap method of the GestureDetector. By calling setState the page gets rebuild once the image has been deleted.

EDIT Sorry, I misread your question and see that you want to show a button below the image, instead of on top of it. A Column widget could be used for this purpose. I edited the code accordingly.

Afflict answered 6/3, 2020 at 15:3 Comment(7)
how to show an alert with yes and no option on tapping the delete button ?Angleworm
Instead of directly deleting the image, call a function which shows an alert message. #53844552Afflict
Where should your code starting with child: be placed ? Container has height:1200, after uploading many images, overflow error occurs. Besides even uploading a single image, there is also an overflow error and Icons.clear does not show up ?Angleworm
This code is just to give you an idea on how you could implement that, I wouldn't copy it directly. I guess changing the color of the clear icon from white to black would make it visible? If you post your code I could check on how you can solve the overflow errors.Afflict
I pasted your code just in the place of Column( children: images_captured ), in my code after removing that part.Angleworm
I added the code snippet I used along with the screenshot in EDIT part.Angleworm
any solution from you as you said in your previous comment ?Angleworm

© 2022 - 2024 — McMap. All rights reserved.