You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建自定义GridView画廊展示外部存储指定文件夹图片?

我明白你现在卡在自定义画廊展示外部指定文件夹图片的问题上了,之前试了各种方案都没成功,别着急,我给你一套完整可行的实现步骤,跟着做应该就能搞定:

第一步:先搞定存储权限

Android从6.0开始就要求动态申请危险权限,存储权限更是重点,不同版本的权限还有区别:

  • 先在AndroidManifest.xml里添加基础权限:
    <!-- Android 12及以下 -->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- Android 13+ -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    
  • 在Activity/Fragment里动态申请权限:
    private static final int REQUEST_STORAGE_PERMISSION = 100;
    
    private void requestStoragePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityResultContracts.RequestMultiplePermissions contract =
                        new ActivityResultContracts.RequestMultiplePermissions();
                registerForActivityResult(contract, result -> {
                    Boolean isGranted = result.get(Manifest.permission.READ_MEDIA_IMAGES);
                    if (isGranted != null && isGranted) {
                        // 权限通过,开始加载图片
                        loadFolderImages();
                    } else {
                        Toast.makeText(this, "需要存储权限才能查看图片", Toast.LENGTH_SHORT).show();
                    }
                }).launch(new String[]{Manifest.permission.READ_MEDIA_IMAGES});
            } else {
                loadFolderImages();
            }
        } else {
            // 处理Android 12及以下的权限申请
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
                    != PackageManager.PERMISSION_GRANTED) {
                ActivityResultContracts.RequestPermission contract =
                        new ActivityResultContracts.RequestPermission();
                registerForActivityResult(contract, isGranted -> {
                    if (isGranted) {
                        loadFolderImages();
                    } else {
                        Toast.makeText(this, "需要存储权限才能查看图片", Toast.LENGTH_SHORT).show();
                    }
                }).launch(Manifest.permission.READ_EXTERNAL_STORAGE);
            } else {
                loadFolderImages();
            }
        }
    }
    
第二步:获取指定文件夹下的所有图片

写一个工具方法,传入你要展示的文件夹路径(比如Environment.getExternalStorageDirectory() + "/MyPictures/"),筛选出所有图片文件:

private List<String> getImagePathsFromFolder(String folderPath) {
    List<String> imagePaths = new ArrayList<>();
    File folder = new File(folderPath);
    if (!folder.exists() || !folder.isDirectory()) {
        Toast.makeText(this, "文件夹不存在", Toast.LENGTH_SHORT).show();
        return imagePaths;
    }

    // 筛选常见的图片格式
    String[] imageExtensions = {"jpg", "jpeg", "png", "gif", "bmp"};
    File[] files = folder.listFiles((dir, name) -> {
        String lowerName = name.toLowerCase();
        for (String ext : imageExtensions) {
            if (lowerName.endsWith("." + ext)) {
                return true;
            }
        }
        return false;
    });

    if (files != null) {
        for (File file : files) {
            imagePaths.add(file.getAbsolutePath());
        }
    }
    return imagePaths;
}
第三步:修改GridView的适配器

把你原来硬编码图片的适配器改成动态加载路径的版本,这里推荐用Glide来加载图片(比原生BitmapFactory更省心,还能处理内存问题),先在build.gradle里添加Glide依赖:

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.16.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
}

然后写适配器:

public class ImageGridAdapter extends BaseAdapter {
    private Context mContext;
    private List<String> mImagePaths;

    public ImageGridAdapter(Context context, List<String> imagePaths) {
        mContext = context;
        mImagePaths = imagePaths;
    }

    @Override
    public int getCount() {
        return mImagePaths.size();
    }

    @Override
    public Object getItem(int position) {
        return mImagePaths.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {
            // 创建新的ImageView,适配GridView的列宽
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, 300 // 可以根据需求调整高度
            ));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(4, 4, 4, 4);
        } else {
            imageView = (ImageView) convertView;
        }

        // 用Glide加载图片
        Glide.with(mContext)
                .load(new File(mImagePaths.get(position)))
                .into(imageView);
        return imageView;
    }
}
第四步:绑定GridView并加载数据

在你的Activity的onCreate方法里,调用权限申请,权限通过后加载图片并设置适配器:

private GridView mGridView;
private ImageGridAdapter mAdapter;
private List<String> mImagePaths;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mGridView = findViewById(R.id.gridview);
    // 先申请权限
    requestStoragePermission();
}

private void loadFolderImages() {
    // 替换成你要展示的文件夹路径
    String targetFolder = Environment.getExternalStorageDirectory() + "/MyCustomGallery/";
    mImagePaths = getImagePathsFromFolder(targetFolder);
    mAdapter = new ImageGridAdapter(this, mImagePaths);
    mGridView.setAdapter(mAdapter);
}
额外注意事项
  • 如果你的目标是Android 10及以上,默认开启了分区存储,不能直接访问其他APP的文件夹,如果你要访问的是自己APP创建的文件夹,或者公共文件夹(比如DCIM、Pictures)是没问题的;如果要访问任意文件夹,需要使用**存储访问框架(SAF)**让用户手动选择文件夹。
  • 记得处理文件夹为空的情况,比如给GridView加个空视图提示用户“当前文件夹没有图片”。
  • Glide可以设置占位图和错误图,提升用户体验,比如:
    Glide.with(mContext)
            .load(new File(mImagePaths.get(position)))
            .placeholder(R.drawable.placeholder)
            .error(R.drawable.error)
            .into(imageView);
    

内容的提问来源于stack exchange,提问作者Disney

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:44:48