Android之图片选择与裁剪

文章来自:点击打开链接


对于现在的应用来说,基本都有用户模块,当然也就涉及到了用户头像的修改问题。修改头像我们一般采用两种方式:调用系统相机进行拍照或从图库中选择图片进行上传。但是由于Rom定制市场的混乱,导致了出现此问题在解决时需要重点考虑了兼容性,下面给出一种通用解决方案。

启动相机进行拍照

需要注意的是,Android系统为了防止传送原图出现OOM,拍照后默认返回的是缩略图,为了解决这种问题,我们在启动相机的时候要先设置照片的存储路径,即传递MediaStore.EXTRA_OUTPUT参数,这样拍照完成后我们就可以根据之前设置的路径读取原图了。

1
2
3
4
5
6
// 设置图片的输出路径
File file = new File(Environment.getExternalStorageDirectory() + "/temp_icon.jpg");
iconUri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, iconUri);
startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);

打开图库选择图片

选择图片操作其实没什么难度,选择完成后默认返回的就是图片的存储路径。

1
2
3
Intent intent = new Intent(Intent.ACTION_PICK, null);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(intent, REQUEST_CODE_CHOOSE_IMAGE);

裁剪图片

和拍照的情况一样,Android为了防止传送大图片出现OOM,在截图的过程中默认传递的也是缩略图,这样裁减后的图片会非常模糊。所以采用URi的方式传递来原图的路径。需要注意的是,如果传递原图,那么拍照时需要设置照片的输出路径,也就是在调用相机时传递MediaStore.EXTRA_OUTPUT参数,同时为了防止某些手机默认传递原图的问题(如小米4),在传递大图片时将return-data置为false;对于某些手机或平板,输入Uri和输出Uri不能相等,否则裁减后的图片大小变为0kb,如平板Teclast P80h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * 裁减图片操作
 * @param uri
 */
private void startCropImage(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    // 使图片处于可裁剪状态
    intent.putExtra("crop", "true");
    // 裁剪框的比例(根据需要显示的图片比例进行设置)
    intent.putExtra("aspectX", 3);
    intent.putExtra("aspectY", 2);
    // 让裁剪框支持缩放
    intent.putExtra("scale", true);
    // 裁剪后图片的大小(注意和上面的裁剪比例保持一致)
    intent.putExtra("outputX", AndroidPlatformUtil.dpToPx(this, 120));
    intent.putExtra("outputY", AndroidPlatformUtil.dpToPx(this, 80));
    // 传递原图路径
    File cropFile = new File(Environment.getExternalStorageDirectory() + "crop_image.jpg");
    cropImageUri = Uri.fromFile(cropFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri);
    // 设置裁剪区域的形状,默认为矩形,也可设置为原形
    //intent.putExtra("circleCrop", true);
    // 设置图片的输出格式
    intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    // return-data=true传递的为缩略图,小米手机默认传递大图,所以会导致onActivityResult调用失败
    intent.putExtra("return-data", false);
    // 是否需要人脸识别
    intent.putExtra("noFaceDetection", true);
    startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE);
}

获取传递的图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    if(intent != null) {
        switch (requestCode) {
        	  // 将拍摄的照片进行裁剪(注意,这里需要传递的是照片的路径,而不是intent.getData(), 因为intent.getData()返回的是缩略图的数据)
            case REQUEST_CODE_TAKE_PHOTO:
                startCropImage(iconUri);
                break;
            // 将选择的图片进行裁剪
            case REQUEST_CODE_CHOOSE_IMAGE:
                if (intent.getData() != null) {
                    iconUri = intent.getData();
                    startCropImage(iconUri);
                }
                break;
            // 将裁剪后的图片进行上传
            case REQUEST_CODE_CROP_IMAGE:
                // 上传图片操作
                break;
            default:
                break;

        }
    } else {
    	// 解决某些手机intent为空的情况
        if (requestCode == REQUEST_CODE_TAKE_PHOTO && iconUri != null) {
            startCropImage(iconUri);
        }
    }
}

总结

通过上面的四步,图片的选择与裁剪就完成了。总的来说,需要注意的只有一点,无论是拍照还是选选择图片到裁剪的过程,只有传递图片的路径才能从根本上实现此问题。否则将出现各种兼容性问题。还有一点需要提醒的是:裁剪是真正决定所要展示图片的比例和大小的。


你可能感兴趣的:(Android)