Android custom image gallery with checkbox in grid to select multiple


Some times we may require to select multiple images from gallery. So using the following method you will be able to select multiple images. Additionally it will also remove gallery app dependency.

It may not be sufficient method as I need to maintain two array in this activity, but it could vary on requirements. Please comment if you have any suggestion in code.

Main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<Button android:id="@+id/selectBtn"
		android:layout_width="wrap_content" android:layout_height="wrap_content"
		android:text="Select" android:layout_alignParentBottom="true"
		android:layout_centerHorizontal="true"
		android:minWidth="200px" />
	<GridView android:id="@+id/PhoneImageGrid"
		android:layout_width="fill_parent" android:layout_height="fill_parent"
		android:numColumns="auto_fit" android:verticalSpacing="10dp"
		android:horizontalSpacing="10dp" android:columnWidth="90dp"
		android:stretchMode="columnWidth" android:gravity="center"
		android:layout_above="@id/selectBtn" />
</RelativeLayout>

galleryitem.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent" android:layout_height="fill_parent">
	<ImageView android:id="@+id/thumbImage" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:layout_centerInParent="true" />
	<CheckBox android:id="@+id/itemCheckBox" android:layout_width="wrap_content"
		android:layout_height="wrap_content" android:layout_alignParentRight="true"
		android:layout_alignParentTop="true" />
</RelativeLayout>

AndroidCustomGalleryActivity.java

package com.isummation.customgallery;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidCustomGalleryActivity extends Activity {
	private int count;
	private Bitmap[] thumbnails;
	private boolean[] thumbnailsselection;
	private String[] arrPath;
	private ImageAdapter imageAdapter;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID };
		final String orderBy = MediaStore.Images.Media._ID;
		Cursor imagecursor = managedQuery(
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
				null, orderBy);
		int image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);
		this.count = imagecursor.getCount();
		this.thumbnails = new Bitmap[this.count];
		this.arrPath = new String[this.count];
		this.thumbnailsselection = new boolean[this.count];
		for (int i = 0; i < this.count; i++) {
			imagecursor.moveToPosition(i);
			int id = imagecursor.getInt(image_column_index);
			int dataColumnIndex = imagecursor.getColumnIndex(MediaStore.Images.Media.DATA);
			thumbnails[i] = MediaStore.Images.Thumbnails.getThumbnail(
					getApplicationContext().getContentResolver(), id,
					MediaStore.Images.Thumbnails.MICRO_KIND, null);
			arrPath[i]= imagecursor.getString(dataColumnIndex);
		}
		GridView imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
		imageAdapter = new ImageAdapter();
		imagegrid.setAdapter(imageAdapter);
		imagecursor.close();

		final Button selectBtn = (Button) findViewById(R.id.selectBtn);
		selectBtn.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				final int len = thumbnailsselection.length;
				int cnt = 0;
				String selectImages = "";
				for (int i =0; i<len; i++)
				{
					if (thumbnailsselection[i]){
						cnt++;
						selectImages = selectImages + arrPath[i] + "|";
					}
				}
				if (cnt == 0){
					Toast.makeText(getApplicationContext(),
							"Please select at least one image",
							Toast.LENGTH_LONG).show();
				} else {
					Toast.makeText(getApplicationContext(),
							"You've selected Total " + cnt + " image(s).",
							Toast.LENGTH_LONG).show();
					Log.d("SelectedImages", selectImages);
				}
			}
		});
	}

	public class ImageAdapter extends BaseAdapter {
		private LayoutInflater mInflater;

		public ImageAdapter() {
			mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		public int getCount() {
			return count;
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				holder = new ViewHolder();
				convertView = mInflater.inflate(
						R.layout.galleryitem, null);
				holder.imageview = (ImageView) convertView.findViewById(R.id.thumbImage);
				holder.checkbox = (CheckBox) convertView.findViewById(R.id.itemCheckBox);

				convertView.setTag(holder);
			}
			else {
				holder = (ViewHolder) convertView.getTag();
			}
			holder.checkbox.setId(position);
			holder.imageview.setId(position);
			holder.checkbox.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					CheckBox cb = (CheckBox) v;
					int id = cb.getId();
					if (thumbnailsselection[id]){
						cb.setChecked(false);
						thumbnailsselection[id] = false;
					} else {
						cb.setChecked(true);
						thumbnailsselection[id] = true;
					}
				}
			});
			holder.imageview.setOnClickListener(new OnClickListener() {

				public void onClick(View v) {
					// TODO Auto-generated method stub
					int id = v.getId();
					Intent intent = new Intent();
					intent.setAction(Intent.ACTION_VIEW);
					intent.setDataAndType(Uri.parse("file://" + arrPath[id]), "image/*");
					startActivity(intent);
				}
			});
			holder.imageview.setImageBitmap(thumbnails[position]);
			holder.checkbox.setChecked(thumbnailsselection[position]);
			holder.id = position;
			return convertView;
		}
	}
	class ViewHolder {
		ImageView imageview;
		CheckBox checkbox;
		int id;
	}
}

Download full source code:
Download

Update: need more features? see my open source project
Update: Please remove code that closes cursor. As this will not work in Android 4.0 and newer.

http://vikaskanani.wordpress.com/android-custom-gallery-and-instant-upload-project/

 

 

 

 

98 thoughts on “Android custom image gallery with checkbox in grid to select multiple

  1. Paresh N Mayani

    Really great work, I am really impressed with the Idea that you have implemented to select multiple images through check box.

    Please post the “galleryitem.xml” layout which you forgot to add here.

    Reply
    1. Mangesh

      Hi thanks for this sample code. I used this in my application. Now i have string which contain path of selected images. I want to upload those images to server using multipart format. But when i give it string path it shows me file not found exception. But when i put those images in gallery view i have them in it.

      Please suggest me solution.

      Reply
  2. Pingback: Android custom image gallery – part 2 – Add capture button and update gallery | Vikas Patel's Blog

  3. debussyster

    Nice job.btw,I want to add a select all button
    for(int i=0;i<thumbnails.length;i++){
    thumbnailsselection[i] = true;
    }

    photoGrid.invalidate();
    but it does not work.

    Reply
  4. Erik Hallberg

    Just what i was looking for thanks.
    I just got this partially working in a android.widget.Gallery.
    Only the ImageView and ChecBox are beside each other
    not overlaying. Any ide how to fix that?

    Reply
  5. weezzz

    Hi ! Great work ! Impressive !

    Btw, do you know how I could get selected image from another activity ? I would like to let user select photos, and use it later in my app. Singleton could be possibly able to do that, but if you have better ideas, I’m listening ;).

    Thx !

    Reply
  6. Bernie Eng (@ebernie)

    A few suggestions:

    1. Use a HashSet to store file paths
    2. Remove the need for a boolean[] by storing the file path in each CheckBox as a Tag object
    3. I retrieve the file path from the checkbox when they are selected and store them in the HashSet. Likewise, I remove the file paths when they are deselected. These ops are done in the OnClickListener.
    4. Instead of keeping a counter and looping through the String[] storing file paths, I know just do a HashSet.isEmpty() to see if there are any photos selected
    5. If there are photos, I simply do a foreach loop on the HashSet to obtain them
    6. Instead of a new OnClickListener for each CheckBox, I only create one instance to be shared across all of them

    note: using checkbox.getId() for array indexes isn’t working for me as they are a very large number and I get a ArrayOutOfBoundsException when using your codes

    Reply
  7. Khizar Aziz

    hey ,
    thanx for the nioce post…. just one problem , using it on a device for the first time crashes the app which i think is because the thumbnails are not already generated …. maybe ….. because when the app is run again it works like a charm … any idea whats the problem here\??

    Reply
  8. vigneshwaran

    hi vikas,
    thank you very much for your code ,this is what i’m looking for ,this code is really helped me.

    Regards,
    vigneshwaran

    Reply
  9. Jai

    Great work!! Thanks. If I were to change this to load images from a remote site, what changes do I need to make?

    Reply
    1. Vinuta

      Hey ! I wanted to know if i can select exactly 4 images using the code as u’ve given?
      I mean, if i select more than 4,the select button shud get disabled…
      Where shud i add the code for this?
      really in need of this ….
      Thanks !

      Reply
  10. Scott Lin

    I am in 2.3 and have over 200 image in my photo gallery, I do see performance issue waiting for 1st screen…..Any idea to make the screen come out fast?

    Reply
  11. andrgsilva

    Hi, Vikas. Thanks for this post. Instead of querying images from device’s gallery, is it possible to query images from built-in wallpaper’s gallery?

    Reply
    1. Vikas Post author

      Hi,

      You can use this code to browse gallery:

      Intent intent = new Intent();
      intent.setType(“image/*”);
      intent.setAction(Intent.ACTION_GET_CONTENT);
      startActivityForResult(
      Intent.createChooser(intent, “Select Picture”),
      PICK_IMAGE);

      And on Activity result, you can get the image from this code:

      Uri selectedImageUri = data.getData();

      Hope that helps.

      Reply
  12. Bala

    Sorry.. One error is occurred for me. Please give solution. The error is
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.isummation.customgallery/com.isummation.customgallery.AndroidCustomGalleryActivity}: java.lang.NullPointerException

    Reply
  13. swathi

    really wel…
    I need to change the selected images randomly on desktop..how can i do this work plz reply me…

    Reply
  14. tatilikitha

    this in code i am unable to go back to thumbnail part after viewing the single selected image in full screen will please help me as soon as possible please

    Reply
  15. D. Viorel

    Hello.
    If I use this custom gallery in a phone with few photos, it’s working, but if I use this in a phone with 200 photo for example, the app freeze.
    A possible solution for this?

    Thank you!

    Reply
    1. Vikas Post author

      It is because your phone may not keep thumbnails, so every time it regenerates thumbnails, which took time. Issue can be solved by putting loading dialog, and read 20/30 images at a time, then dynamically load others.

      Reply
  16. victor

    Hi. I’m using your gallery. And it works nice, but when i select images with a significative weight then the gallery crashes. Why? Thanks in advance.

    Reply
    1. Vikas Post author

      I’ve added updates, in ICS and jelly bean, you don’t need to close the cursor, so remove that code. This causes the crash.

      Reply
  17. vysakhp

    Dear Vikas

    If possible please can you please upload the full source code to another site. The present site requires sign up which I don’t want to do.

    Reply
  18. Gabriel

    Vikas,

    could you attach some license and copyright to this code? I’d like to use it but the company lawyers are not happy until there is something legalese attached… :-)

    Thanks,
    Gabriel

    Reply
  19. Fernando Fernandes

    Great work, Vikas!

    Any ideas on how to improve the performance?

    In a device with 568 images, it takes a looooong time to load all the thumbs and put them into the grid. :-(

    Thanks in advance,
    – Fernando

    Reply
    1. Bharath

      Hi did you solve this problem of loading too many images.
      Can I start this on async task to reduce the load on main UI thread?

      Reply
  20. Archie

    How do I delete and image adn checkbox when checkbox selection is made. I can easily delete the image, not the checkbox until i exit the activity and come back.

    Reply
  21. Aditi

    Thanks for this application… Now I want to display selected images on imageviews in next activity.. Can you please help me?

    Reply
  22. Aditi

    Please tell me how do i can display selected images in imageview? I can show only single image but i want to show multiple images.

    Reply
  23. hari

    when i tried to use your code in android 4.1 it crashed . . and cn u please say where is your updation for the new versions?

    Reply
  24. Manohar Choudhary

    (Uri.parse(“file://” + arrPath[id]), “image.jpg”); in this how i set file path coz its not working so plz give me suggestion

    Reply
  25. VijayRaj

    Hi Vikas,

    Great example…This is exactly I was looking for :)

    However, while using this example in v4.1, I frequently get couple of errors while forming the Custom Gallery of around 500 images
    1)android.data.staledataexception—it says I am trying to access cursor even after closing it.. As you mentioned, I am not closing the cursor..I have removed this line imgcursor.close() from the above example..but sometimes I still get this error :(
    2)java.lang.OutOfMemmoryError—-this error occurs while getting the thumbnail of the image

    Can you pls help share some knowledge about the two errors and how to overcome this issues?

    Thanks,
    VijayRaj

    Reply
  26. Peter

    There is a problem with the gallery when larger thumbnails (MINI_KIND) or many pictures are displayed: it wastes a lot of memory. The solution is to remove the thumbnail loading from the main activity, only storing the paths and IDs. The actual loading of the bitmap thumbnail should only come in getView().

    Reply
      1. stephen

        Here’s what I did. Remove the Bitmap from the ImageItem:
        class ImageItem {
        boolean selection;
        int id;
        //Bitmap img;
        }
        Fix all resulting errors.

        Modify the end of getView (where you setup the holder) to the following:
        Bitmap thumbnail = MediaStore.Images.Thumbnails.getThumbnail(getApplicationContext().getContentResolver(), item.id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
        holder.imageview.setImageBitmap(thumbnail);
        holder.checkbox.setChecked(item.selection);

        return convertView;

    1. Anders da Silva

      I have good use of Vikas class, but i have to agree with previous comment, i tried the tip – I am now loading images one-by-one in getView and it is seems much faster than loading everything in onCreate.

      Reply
    2. stephen

      Thanks, I was just looking into that. Lazy loading is a must here. But, take note that loading from the SD card will create noticeable delays proportional to the number of images on the SD card. This is a physics problem. It would be hard if not impossible to program your way around it considering the resource limitations on mobile devices.

      Reply
  27. momna

    hi

    im unable to see images and check boxes when i run your source code .can u please guide me what is required to make this code functional on my machine ?

    Reply
  28. Priyanka

    Hey really that is an impressive one..
    Thanx a lot Vikas..
    One more thing.. How can I copy all the selected images to a folder..??
    Can you please help me with this..

    Reply
  29. Priyanka

    hey..thats really an impressive one..
    thanx a lot Vikas..
    One more thing.. how can i copy the images selected to a folder in sdcard..??
    Please help me with thiss…

    Reply
    1. gaurav

      your code helped me so much…. thanks but i need more help…. i want to hide selected images when click on checkbox…… pls rply early as soon as possible… thanks in andvnace

      Reply
  30. Pingback: android select multiple images from gellery and save sd card | BlogoSfera

  31. Pingback: android select multiple images from gellery and save sd card - How-To Video

  32. Pingback: how to save selected image in database - How-To Video

  33. Pingback: how to save selected image in database - Tech Forum Network

  34. Pingback: how to load images from application memory in gridview - How-To Video

  35. Pingback: multiple image chooser with select all function Android Library - How-To Video

  36. Natesh

    I have an error in this line even i download this project and import it. Can u please heip me to come out of this error.
    image_column_index = imagecursor.getColumnIndex(MediaStore.Images.Media._ID);

    Reply
  37. Pingback: How to load images from application memory in GridView | BlogoSfera

  38. Ujjwal Bose

    thanx for this needy example…bt i hv got a problem that is my vars. arrpath and thumbnails and not being recognised in imageadapter class so the gridview is not displayed..how to solve it please help me…ASAP

    Reply
  39. Ann Tare Woo

    Thanks for your very good code.
    I have a question for you.
    Can I use part of the sources at my contest application?

    Reply
  40. Claudio Sconosciuto

    i think the code could be better this way:
    toggle the state from selectable to not selectable.
    and this coulbe done with
    flag = false;
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
    super.bindView(view, context, cursor);
    view.setTag();
    CheckBox ckbox= (CheckBox) view.findViewById(R.id.itemCheckBox);
    if (flag) {
    ckbox.setVisibility(View.VISIBLE);
    }
    else
    ckbox.setVisibility(View.GONE);

    this way you can switch from multiselect mode to another mode, in which you can do more..
    anyway, its a flawless and great code! thanks for sharing

    Reply
  41. Viveka Patel

    Thanks vikas ….very good code its very useful for me….
    i have one question please solve this…
    when i choose multiple images and click on button at that time all selected images are pass and show in another activity.
    how can i do,,??
    give me any idea for do that.
    thanks in advance…

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s