使用GridView从SD卡上特定文件夹显示图片

10

我正在尝试创建一个GridView,其中加载了一个特定文件夹(位于SDCard上)中的图像。该文件夹的路径已知为("/sdcard/pictures") ,但是在我看到的在线示例中,我不确定在哪里或如何指定要从中加载图像的图片文件夹的路径。我已经阅读了数十个教程,甚至包括developer.android.com上的HelloGridView教程,但这些教程都没有教会我我在寻求的内容。

到目前为止,我阅读过的每个教程都:

A) 从/res文件夹中以Drawable形式调用图像并将它们放入数组中进行加载,根本没有使用SDCard。

B) 使用MediaStore访问SDCard上的所有图片,但未指定如何设置要显示图像的文件夹的路径。

或者

C) 建议使用BitmapFactory,但我不知道如何使用。

如果我走错了路,请告诉我并引导我找到正确的方法来完成我的尝试。

6个回答

15

好的,在多次尝试后,我终于有了一个可行的示例,并且我想分享它。我的示例查询图像MediaStore,然后获取每个图像的缩略图以在视图中显示。我将我的图像加载到一个Gallery对象中,但这并不是此代码工作的要求:

确保您在类级别上定义了Cursor和int列索引,以便Gallery的ImageAdapter可以访问它们:

private Cursor cursor;
private int columnIndex;

首先,获取位于文件夹中的图像ID的光标:

Gallery g = (Gallery) findViewById(R.id.gallery);
// request only the image ID to be returned
String[] projection = {MediaStore.Images.Media._ID};
// Create the cursor pointing to the SDCard
cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        projection, 
        MediaStore.Images.Media.DATA + " like ? ",
        new String[] {"%myimagesfolder%"},  
        null);
// Get the column index of the image ID
columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
g.setAdapter(new ImageAdapter(this));

然后,在Gallery的ImageAdapter中获取要显示的缩略图:

public View getView(int position, View convertView, ViewGroup parent) {
    ImageView i = new ImageView(context);
    // Move cursor to current position
    cursor.moveToPosition(position);
    // Get the current value for the requested column
    int imageID = cursor.getInt(columnIndex);
    // obtain the image URI
    Uri uri = Uri.withAppendedPath( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Integer.toString(imageID) );
    String url = uri.toString();
    // Set the content of the image based on the image URI
    int originalImageId = Integer.parseInt(url.substring(url.lastIndexOf("/") + 1, url.length()));
    Bitmap b = MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(),
                    originalImageId, MediaStore.Images.Thumbnails.MINI_KIND, null);
    i.setImageBitmap(b);
    i.setLayoutParams(new Gallery.LayoutParams(150, 100));
    i.setScaleType(ImageView.ScaleType.FIT_XY);
    i.setBackgroundResource(mGalleryItemBackground);
    return i;
}

我猜这段代码最重要的部分是managedQuery,它演示了如何使用MediaStore查询来过滤特定文件夹中的图像文件列表。


谢谢提供示例代码 :) - venkat
@achilldress:你好,我完全按照你的代码操作了。但是我发现columnIndex是0,而且cursor不为空。这看起来有些不对劲,你知道为什么吗?请告诉我。谢谢。 - Huy Tower
我从索引0获取的imageID为空。android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0 - Huy Tower
现在,managedQuery已经被弃用了,而且由于某个未知原因,在这里游标始终为null。 - Adi Prasetyo

4
您需要比developer.android.com上的GridView教程多做几个步骤。使用以下教程:http://developer.android.com/resources/tutorials/views/hello-gridview.html 您需要添加一个方法来创建ImageView并显示来自sd卡的文件:
请在类变量中创建/添加一个向量(以保存ImageView列表):
private Vector<ImageView> mySDCardImages;

初始化向量:

mySDCardImages = new Vector<ImageView>();

创建一个加载图片的方法:
List<Integer> drawablesId = new ArrayList<Integer>();
int picIndex=12345;
File sdDir = new File("/sdcard/pictures");
File[] sdDirFiles = sdDir.listFiles();
for(File singleFile : sdDirFiles)
{
   ImageView myImageView = new ImageView(context);
   myImageView.setImageDrawable(Drawable.createFromPath(singleFile.getAbsolutePath());
   myImageView.setId(picIndex);
   picIndex++;
   drawablesId.add(myImageView.getId());
   mySDCardImages.add(myImageView);
}
mThumbIds = (Integer[])drawablesId.toArray(new Integer[0]);

在您的ImageAdapter方法中,请更改下面的内容:
imageView.setImageResource(mThumbIds[position]);

to

imageView.setImageDrawable(mySDCardImages.get(position).getDrawable());

将mThumbIds的初始化从ImageAdapter中移除,它应该与mySDCardImages的定义一起。对于两个类方法都是可访问的。

(快速而简单的版本) 确保测试您的路径等,并捕获任何异常。


嗨,我使用了http://developer.android.com/guide/topics/ui/layout/gridview.html#example这个链接中的代码,并想将其更改为从SD卡获取文件。您能告诉我在您的代码中应该在哪里以及写哪一部分吗?谢谢 - Iosif
如果你想把它作为一个问题发布,我会回答它。在这里评论中,我不知道我能不能很好地回答那个问题。 - VMcPherron

3
在你的情况下,BitmaFactory可能是一个不错的选择。例如:
File dir = new File( "/sdcard/pictures" );    
String[] fileNames = dir.list(new FilenameFilter() { 
  boolean accept (File dir, String name) {
      if (new File(dir,name).isDirectory())
         return false;
      return name.toLowerCase().endsWith(".png");
  }
});
for(string bitmapFileName : fileNames) {
  Bitmap bmp = BitmapFactory.decodeFile(dir.getPath() + "/" + bitmapFileName);
  // do something with bitmap
}

现在没有时间测试,但应该可以工作;-)


谢谢你的回复,evilcroco。我正在测试你的代码! - Jevarlo

0

看起来你想要自定义相册,这需要花费很多时间。

我建议你使用自定义相机相册来完成你的工作。

你将会得到你想要的照片/视频网格视图。


0

阅读此链接:http://androidsamples.blogspot.com/2009/06/how-to-display-thumbnails-of-images.html
它展示了如何同时使用mediastore和bitmapfactory。

你应该选择的方式取决于你需要什么。如果你有一组静态图像,我认为最好将它们放在drawable中,因为这样更快,而且你不依赖于SD卡,它可能会被移除、损坏或文件可能被重命名/删除

如果图像是动态的,则使用mediastore或bitmap factory。但请记住,将图像放入数组或其他东西会消耗大量内存,因此你可能会遇到outofmemory异常


感谢您的回复!我已经按照教程编译成功了,但是我遇到了一个问题,就是无法更改从哪个文件夹路径加载图像。不过我在评论中读到了可以更改文件夹路径查询的方法。我的问题是:我应该在“imagecursor = managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, img, null, null, MediaStore.Images.Thumbnails.IMAGE_ID +“”);”处更改查询吗?它接受字符串作为参数吗? - Jevarlo

0

对于 Kotlin 代码,请参见此 问题 的答案。

这个想法也适用于 Java(但您需要修改代码)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接