Android 使用gridview显示SD卡上特定文件夹中的图像

Android 使用gridview显示SD卡上特定文件夹中的图像,android,gridview,uri,android-sdcard,bitmapfactory,Android,Gridview,Uri,Android Sdcard,Bitmapfactory,我正在尝试创建一个gridview,其中加载了SD卡上特定文件夹中的图像。文件夹的路径是已知的(“/sdcard/pictures”),但在我在线看到的示例中,我不确定如何或在何处指定要从中加载图像的图片文件夹的路径。我已经阅读了几十篇教程,甚至是developer.android.com上的HelloGridView教程,但这些教程并没有教会我在寻找什么 到目前为止,我阅读的每一篇教程都有: A) 从/res文件夹中将图像作为可绘制文件调用,并将其放入要加载的数组中,而不使用SD卡 B) 使用

我正在尝试创建一个gridview,其中加载了SD卡上特定文件夹中的图像。文件夹的路径是已知的(“/sdcard/pictures”),但在我在线看到的示例中,我不确定如何或在何处指定要从中加载图像的图片文件夹的路径。我已经阅读了几十篇教程,甚至是developer.android.com上的HelloGridView教程,但这些教程并没有教会我在寻找什么

到目前为止,我阅读的每一篇教程都有:

A) 从/res文件夹中将图像作为可绘制文件调用,并将其放入要加载的数组中,而不使用SD卡

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

C) 建议使用BitmapFactory,我一点也不知道如何使用它

如果我用了错误的方法,请让我知道,并指导我正确的方法去做我想做的事情

阅读此链接:
它展示了如何同时使用mediastore和bitmapfactory

你应该选择的方式取决于你到底需要什么。如果你有一组静态的图像,我认为最好将它们放在绘图设备上,因为这样做速度更快,而且你不需要依赖sd卡,sd卡可以被删除、损坏或重命名/删除文件


如果图像是动态的,则使用mediastore或位图工厂。但请记住,将图像放入数组或其他相当耗费内存的东西中,因此最终可能会出现outofmemory异常。在您的情况下,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
}

没有时间测试这一点,但应该可以工作;-)

您需要比developer.android.com上的GridView教程多做几个步骤。使用以下教程

您需要添加一种方法,从sd卡创建文件的ImageView:

创建/向类变量添加向量(以保存ImageView列表):

从ImageAdapter中删除mThumbIds的初始化。(它应该符合mySDCardImages的定义。这两个类方法都可以访问。)


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

好的,经过多次尝试,我终于有了一个有效的示例,我想与大家分享。我的示例查询images MediaStore,然后获取要在视图中显示的每个图像的缩略图。我正在将图像加载到Gallery对象中,但这不是此代码工作的要求:

确保在类级别为列索引定义了游标和int,以便库的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));
然后,在库的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查询来过滤特定文件夹中的图像文件列表。

看起来您想要定制gallerry,这将花费您很多时间

我建议你好好工作


您将在网格视图中获得所需的照片/视频。

有关Kotlin代码,请参阅此问题的答案


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

谢谢您的回复!我已经按照教程进行了编译,但在更改从中加载图像的文件夹路径时遇到了问题。不过,我确实在评论中读到,您可以更改文件夹路径查询。我的问题是:我会在“imagecursor=managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,img,null,null,null,MediaStore.Images.Thumbnails.IMAGE_ID+”)处更改查询吗?它是否接受字符串作为参数?感谢您的回复,我现在正在测试您的代码!嗨,我用过这个,我想把它改成从SD卡获取文件。你能告诉我你的代码要写在哪里和哪一部分吗?谢谢如果你想把它作为一个问题发布,我会回答的。我不知道我能否在这里的评论中很好地回答这个问题。谢谢你的示例:)@AchillAddress:你好,我完全按照你的代码进行了操作。但是我的log
columnIndex
为0,
cursor
不为空。看起来好像不对,你知道为什么吗?请告诉我。谢谢。我从索引0获得的
imageID
为空
android.database.CursorIndexOutOfBoundsException:请求索引0,大小为0
managedQuery现在已被弃用,由于未知原因,此处的光标始终为空。
imageView.setImageResource(mThumbIds[position]);
imageView.setImageDrawable(mySDCardImages.get(position).getDrawable());
private Cursor cursor;
private int columnIndex;
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));
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;
}