Friday, April 22, 2011

HelloGallery, read picture files from SD, display in ImageView.

It's a old exercise "HelloGallery, read picture files from SD, using File ArrayList" to demonstrate how to use Gallery. It's modified to add a ImageView to show the large version of the clicked item in Gallery.

HelloGallery, read picture files from SD, display in ImageView.

Create a file /res/values/attrs.xml.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Theme">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>


Modify /res/layout/main.xml to include a Gallery and ImageView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Gallery
android:id="@+id/gallery"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/imageview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
</LinearLayout>


Main code, HelloGallery.java.
package com.exercise.HelloGallery;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

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

final ImageView imageView = (ImageView)findViewById(R.id.imageview);

Gallery g = (Gallery) findViewById(R.id.gallery);
final List<String> SD = ReadSDCard();
g.setAdapter(new ImageAdapter(this, SD));

g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {

String imageInSD = SD.get(position);

Toast.makeText(HelloGallery.this,
imageInSD,
Toast.LENGTH_LONG).show();

Bitmap bitmap = BitmapFactory.decodeFile(imageInSD);
imageView.setImageBitmap(bitmap);

}
});
}

private List<String> ReadSDCard()
{
List<String> tFileList = new ArrayList<String>();

//It have to be matched with the directory in SDCard
File f = new File("/sdcard/pictures/");

File[] files=f.listFiles();

for(int i=0; i<files.length; i++)
{
File file = files[i];
//add the selected file type only
String curFile=file.getPath();
String ext=curFile.substring(curFile.lastIndexOf(".")+1,
curFile.length()).toLowerCase();
if(ext.equals("jpg")||ext.equals("gif")||ext.equals("png"))
tFileList.add(file.getPath());
}

return tFileList;
}

public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private List<String> FileList;

public ImageAdapter(Context c, List<String> fList) {
mContext = c;
FileList = fList;
TypedArray a = obtainStyledAttributes(R.styleable.Theme);
mGalleryItemBackground = a.getResourceId(
R.styleable.Theme_android_galleryItemBackground,
0);
a.recycle();
}

public int getCount() {
return FileList.size();
}

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

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

public View getView(int position, View convertView,
ViewGroup parent) {
ImageView i = new ImageView(mContext);

Bitmap bm = BitmapFactory.decodeFile(
FileList.get(position).toString());
i.setImageBitmap(bm);

i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);

return i;
}
}
}


Download the files.


next:
- HelloGallery, read picture files from SD, display in ImageView, and set as Wallpaper

6 comments:

Unknown said...

This was very useful to me. I ran into a little bit of trouble running my VM out of memory using pictures that were just slightly too large. I found an interesting trick on stack overflow to scale your images before trying to decode and display them. Here is what I hacked together, which works really well ...

snip! ------- >8

g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
String imageInSD = SD.get(position);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;

// The new size we want to scale to
final int REQUIRED_SIZE=70;
// Find the correct scale value. It should be the power of 2.
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;

bitmap = BitmapFactory.decodeFile(imageInSD, o2);

imageView.setImageBitmap(bitmap);
}
});

snip!! 8< -----

Erik said...

thx:)

Steve Ballantyne said...

Hello, I have a curious question:

I am trying to use my current "position" to identify my place in the array for the purpose of using the image displayed, and to play with gestures. The problem I have is that if I try to use the int position outside of the adapter, it's value is always returned as '0'. So I have placed a long press listener which tries to set the wallpaper using the currently selected bitmap. But it always uses the first bitmap from the list, because position is always '0'.

Do you have any ideas on how I could get around that?

Erik said...

hello Steve Ballantyne,

Have you update the functions getCount(), getItem() and getItemId() of your ImageAdapter to return FileList.size(), position and position?

The auto-generated default return have is 0, null and 0, it have to be changed manually.

I test the exercise again, it should be work as expected.

Karlosbboy said...

I have a problem, every time I install it on my device displays an error whenever I view the third photo in the emulator but that does not eclipse happens what do can this happening?

Erik said...

hello Karlosbboy,

Do the third is a big photo? Please note that it cannot load big photo, or out of memory will happen. You have to re-size it before display, if it's the case.