EDIT : I've thrown together a working example for you. It works like this:
It will start within a directory (in the example below, /storage/sdcard/DCIM/
). If the directory contains any images, they will be displayed. If it contains any sub-directories, it will check to see if they contain either images, or their own sub-directories. If they do, a folder icon will be displayed. Clicking on the folder icon will open up the folder, and show the images/ sub-directories that it contains.
Please note that this is just intended to give you a rough idea of how to implement it-- you will still need to work on this code a bit to improve the efficiency, especially in terms of memory usage, but I've run this on my emulator and the code is working.
Within your activity
public class MainActivity extends Activity implements OnItemClickListener {
List<GridViewItem> gridItems;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setGridAdapter("/storage/sdcard/DCIM/");
}
/**
* This will create our GridViewItems and set the adapter
*
* @param path
* The directory in which to search for images
*/
private void setGridAdapter(String path) {
// Create a new grid adapter
gridItems = createGridItems(path);
MyGridAdapter adapter = new MyGridAdapter(this, gridItems);
// Set the grid adapter
GridView gridView = (GridView) findViewById(R.id.gridView);
gridView.setAdapter(adapter);
// Set the onClickListener
gridView.setOnItemClickListener(this);
}
/**
* Go through the specified directory, and create items to display in our
* GridView
*/
private List<GridViewItem> createGridItems(String directoryPath) {
List<GridViewItem> items = new ArrayList<GridViewItem>();
// List all the items within the folder.
File[] files = new File(directoryPath).listFiles(new ImageFileFilter());
for (File file : files) {
// Add the directories containing images or sub-directories
if (file.isDirectory()
&& file.listFiles(new ImageFileFilter()).length > 0) {
items.add(new GridViewItem(file.getAbsolutePath(), true, null));
}
// Add the images
else {
Bitmap image = BitmapHelper.decodeBitmapFromFile(file.getAbsolutePath(),
50,
50);
items.add(new GridViewItem(file.getAbsolutePath(), false, image));
}
}
return items;
}
/**
* Checks the file to see if it has a compatible extension.
*/
private boolean isImageFile(String filePath) {
if (filePath.endsWith(".jpg") || filePath.endsWith(".png"))
// Add other formats as desired
{
return true;
}
return false;
}
@Override
public void
onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (gridItems.get(position).isDirectory()) {
setGridAdapter(gridItems.get(position).getPath());
}
else {
// Display the image
}
}
/**
* This can be used to filter files.
*/
private class ImageFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
return true;
}
else if (isImageFile(file.getAbsolutePath())) {
return true;
}
return false;
}
}
}
Then you need to create the adapter, which should extend BaseAdapter, and look like this.
public class MyGridAdapter extends BaseAdapter {
LayoutInflater inflater;
List<GridViewItem> items;
public MyGridAdapter(Context context, List<GridViewItem> items) {
this.items = items;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.grid_item, null);
}
TextView text = (TextView) convertView.findViewById(R.id.textView);
text.setText(items.get(position).getPath());
ImageView imageView = (ImageView) convertView.findViewById(R.id.imageView);
Bitmap image = items.get(position).getImage();
if (image != null){
imageView.setImageBitmap(image);
}
else {
// If no image is provided, display a folder icon.
imageView.setImageResource(R.drawable.your_folder_icon);
}
return convertView;
}
}
And you need to create a class that represents each grid item
public class GridViewItem {
private String path;
private boolean isDirectory;
private Bitmap image;
public GridViewItem(String path, boolean isDirectory, Bitmap image) {
this.path = path;
this.isDirectory = isDirectory;
this.image = image;
}
public String getPath() {
return path;
}
public boolean isDirectory() {
return isDirectory;
}
public Bitmap getImage() {
return image;
}
}
A class for working with images
public abstract class BitmapHelper {
public static Bitmap decodeBitmapFromFile(String imagePath,
int reqWidth,
int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, options);
// Calculate inSampleSize
options.inSampleSize = calculateSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(imagePath, options);
}
private static int calculateSampleSize(BitmapFactory.Options options,
int reqHeight,
int reqWidth) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridView"
android:numColumns="auto_fit"
android:gravity="center"
android:columnWidth="150dp"
android:stretchMode="columnWidth"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
</GridView>
grid_item.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="150dp"
android:layout_height="150dp"
android:padding="5dp" >
<ImageView
android:id="@+id/imageView"
android:layout_width="150dp"
android:layout_height="150dp"
android:scaleType="centerCrop"
android:src="@drawable/andrew_salgado" >
</ImageView>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="20dp"
android:layout_alignParentBottom="true"
android:alpha="0.8"
android:background="#000000" >
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="start"
android:singleLine="true"
android:textColor="#FFFFFF" />
</RelativeLayout>
</RelativeLayout>