前言
已经完整打包成一个工具 , 添加了图像压缩和修改了图像剪裁功能 , 项目地址在这里
本篇讲的是使用 “Intent.ACTION_PICK” 来选取图片并进行剪裁加载的操作 , 包括以下两个功能
- 从本地相册读取图片进行剪裁
- 从照相机获取图片进行剪裁
注意: 本篇使用一个工具类PickUriUtils 使Uri转换成文件路径 , 工具类在文章最后给出. 本文的Bitmap对象没有进行回收和缓存 , 在真正的使用中是需要进行相关的操作的 , 由于这里是演示 , 就不做多余的处理了.
技术注意点
1.返回值区别
因为我们的选图是通过第三方的选图应用来操作的 , 所以他们之间可能会有些区别 , 我们要特别注意!!
获取剪裁图片一般会有两个过程 , 第一步是获取图像 , 第二步是剪裁图像 , 每一步的返回数据会有以下的类型
- 返回Context Uri路径 —— 同时携带Bitmap对象
- 返回文件 Uri路径 —— 同时携带Bitmap对象
- 仅仅返回Bitmap对象
携带Bitmap对象需要”return-data” 为 true 的状态下 , 如果为 false ,在某些选图软件则什么东西都不会返回来 , 所以返回Bitmap对象是必须的 , 但我们可以选择性使用
2.文件解析异常
在某些图库裁剪之后生成的图像文件无法被 BitmapFactory.decodeFile 解析出来 , 但这个过程是没有异常产生的 , 这时候我们就只能使用到携带的 Bitmap 对象了.
3.选取&剪裁流程区别
在一些图库中 , 你选取完图像之后会启动自带的剪裁工具进行剪裁 或 启动第三方应用剪裁 , 这是最理想的状态. 但有的图库选取完了之后不会启动任何剪裁界面 , 而且直接返回一个Uri路径 , 这时候我们就需要单独对返回的图像进行剪裁.
开始编码
主要的注意点说完了 , 下面我们就开始正式编码! 我们一个个功能来做.剩下的一些细小的注意点我们边写边说.
1.使用到的参数变量
//请求码
private final int REQUEST_PERMISSION = 300;
private final int REQUEST_CAMERA = 301;
private final int REQUEST_LOCAL = 302;
private final int REQUEST_CUT = 303;
//请求参数
//临时储存点1
private final String TEMPSAVE_PATH = Environment.getExternalStorageDirectory().getPath()+"/temp.jpg";
//临时储存点2
private final String TEMPSAVE_PATH2 = Environment.getExternalStorageDirectory().getPath()+"/temp2.jpg";
//剪裁图像的长
private final int PICTURE_WIDTH = 200;
//剪裁图像的高
private final int PICTURE_HEIGHT = 200;
//用于显示的ImageView
ImageView shower;
//用于储存得到的Bitmap对象
Bitmap bitmap;
2.从图库选择图像
请求Intent构建
/**
* 启动图片选取界面
*/
private void requestPickFromLocal(){
//我们需要将选取到的图像
File tempFile = new File(TEMPSAVE_PATH);
try {
//创建临时文件
tempFile.createNewFile();
Intent intent = new Intent(Intent.ACTION_PICK,null);
//选取的是图像类型
intent.setType("image/*");
//请求剪裁 (不一定有卵用)
intent.putExtra("crop", "true");
//X轴剪裁比例 , 一般为 1
intent.putExtra("aspectX", 1);
//Y轴剪裁比例 , 一般为 1
intent.putExtra("aspectY", 1);
//X轴剪裁长度
intent.putExtra("outputX", PICTURE_WIDTH);
//Y轴剪裁长度
intent.putExtra("outputY", PICTURE_HEIGHT);
//是否将剪裁后的图像以Bitmap返回
intent.putExtra("return-data", true);
//是否允许缩放 (不一定有卵用)
intent.putExtra("scale", true);
//文件输出格式 (不一定有卵用)
intent.putExtra("outputFormat" , Bitmap.CompressFormat.JPEG.toString());
//不进行脸部识别 (不一定有卵用)
intent.putExtra("noFaceDetection", true);
//得到的文件对象存放的位置 , 以Uri路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
startActivityForResult(intent, REQUEST_LOCAL);
} catch (IOException e) {
Toast.makeText(MainActivity.this, "无法创建临时文件", Toast.LENGTH_SHORT).show();
tempFile = null;
}
}
处理从图库操作后得到的数据
/**
* 处理本地选取图片后的结果
* @param intent 返回的结果 Intent
* @return 0:失败 1:成功 2:还需要进行剪裁处理
*/
private int handlePickFromLocal(Intent intent){
if(intent == null){
//Intent 为空 , 则这次的请求失败
return 0;
}else if (intent.getData() != null){
// Intent 携带有 Uri 路径 , 我们优先使用它
String resultPath = PickUriUtils.getPath(MainActivity.this , intent.getData());
if (resultPath.equals(TEMPSAVE_PATH)){
//如果返回的路径和指定的临时路径相同 , 则说明图片已经剪裁过 , 否则没有
this.bitmap = BitmapFactory.decodeFile(TEMPSAVE