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

Android Studio中使用ActivityResultLauncher选图库图片后无三方库实现1:1裁剪

实现方案(无第三方库,兼容API 16+)

你可以直接调用Android系统原生的裁剪组件实现需求,仅需要新增裁剪逻辑和配套的ActivityResultLauncher即可,以下是完整实现步骤:


1. 前置配置(适配高版本系统文件访问)

首先在AndroidManifest.xml中添加权限和FileProvider配置,避免Android 7.0+以上的Uri暴露异常:

<!-- 必要权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />

<application ...>
    <!-- FileProvider配置 -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${你的应用包名}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

然后在res/xml目录下新建file_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_images" path="Pictures" />
</paths>

2. 声明两个ActivityResultLauncher

替换你原有代码的Launcher声明,新增裁剪结果接收的Launcher:

// 1. 图库选图Launcher
ActivityResultLauncher<String> pickImageLauncher = registerForActivityResult(
        new ActivityResultContracts.GetContent(),
        result -> {
            if (result != null) {
                // 选图成功,启动系统裁剪
                startCrop(result);
            }
        }
);

// 2. 裁剪结果接收Launcher
ActivityResultLauncher<Intent> cropImageLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        result -> {
            if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                // 裁剪成功,加载到ImageView
                Uri croppedUri = Uri.fromFile(cropOutputFile);
                Picasso.with(MainActivity.this).load(croppedUri).into(shapeableImageView);
            }
        }
);

// 全局变量,保存裁剪后输出的文件
private File cropOutputFile;

3. 实现裁剪启动方法

private void startCrop(Uri sourceUri) {
    // 先创建裁剪后输出的文件
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    try {
        cropOutputFile = File.createTempFile(
                "cropped_" + System.currentTimeMillis(),
                ".jpg",
                storageDir
        );
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }

    Uri outputUri;
    // 适配Android 7.0+的Uri获取
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        outputUri = FileProvider.getUriForFile(
                this,
                "${你的应用包名}.fileprovider",
                cropOutputFile
        );
    } else {
        outputUri = Uri.fromFile(cropOutputFile);
    }

    // 构建裁剪意图
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setDataAndType(sourceUri, "image/*");
    // 配置裁剪参数
    intent.putExtra("crop", "true");
    // 1:1裁剪比例
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    // 裁剪输出的分辨率,可根据需求调整
    intent.putExtra("outputX", 500);
    intent.putExtra("outputY", 500);
    intent.putExtra("scale", true);
    intent.putExtra("return-data", false);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri);
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());

    cropImageLauncher.launch(intent);
}

4. 原有选图触发方法保持不变

private void openImagePicker() {
    pickImageLauncher.launch("image/*");
}

注意事项

  • 请把代码中${你的应用包名}替换为你项目实际的包名,和Manifest里的authorities保持一致
  • 部分国产定制系统可能裁剪组件存在兼容性问题,但覆盖95%以上的主流机型完全没问题
  • 如果不需要保存裁剪后的文件到本地,也可以直接读取outputUri的Bitmap使用,避免占用存储空间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:48:02