拍照以及裁剪功能在有些项目中还是经常能遇到的,一般而言,使用拍照和裁剪功能基本上都是使用系统自带的Intent来实现,看起来很简单,但是其中还是有一些问题需要注意的。
这里我们要实现一个功能,点击Button启动系统相机,拍照后将照片显示到按钮下方的ImageView中。
先看看拍照和裁剪对应的动作;
拍照:
MediaStore.ACTION_IMAGE_CAPTURE
裁剪:
com.android.camera.action.CROP
下面看一下裁剪时用的一些参数:
这些参数是选择性的使用的,可以根据你的需求来选择,这些参数里面,
我重点讲一下return-data,MediaStore.EXTRA_OUTPUT这两个参数。
return-data:这里我会将这个参数一直设置为false,因为如果设置为true,就无法将得到的图片设置给我们的ImageView了,所以我们使用Uri来输出。
1.仅拍照
首先因为我们要使用sd卡路径,所以先添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/
然后构建一个图片地址的Uri:
imageuri = Uri.fromFile(createImageFile(".jpg"));
下面是创建Uri的方法的代码:
private File createImageFile(String prefix) {
File image = null;
String timeStamp = new SimpleDateFormat("yyyy_MM_dd_hh_MM_ss")
.format(new Date());
String imageName = prefix+"_JPEG_" + timeStamp + "_";
File imageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
try {
image = File.createTempFile(imageName, ".jpg", imageDir);
} catch (IOException e) {
image = null;
e.printStackTrace();
}
return image;
}
然后通过Intent来启动照相机,设置参数:
Intent intent = null;
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, ACTION_TAKE);
大家可能对return-data和MediaStore.EXTRA_OUTPUT的作用有些迷糊;
return-data:是将结果保存在data中返回,在onActivityResult中,直接调用intent.getdata()就可以获取值了,这里设为fase,就是不让它保存在data中,
MediaStore.EXTRA_OUTPUT:由于我们不让它保存在Intent的data域中,但我们总要有地方来保存我们的图片啊,这个参数就是转移保存地址的,对应Value中保存的URI就是指定的保存地址。
在onActivityResult()中接收:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode!= Activity.RESULT_OK){
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode){
case ACTION_TAKE:
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(bitmap));
imageView.setImageBitmap(bitmap);
break;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
break;
}
我们接收到Bitmap以后设置给ImageView,但是在有的手机上并不会显示出来,我们去看目录下的文件的确实产生了,那为什么会不显示呢,因为图片太大了,超出ImageView的显示范围。所以一般如果要显示的话,需要裁剪一下。
2。拍照并裁剪
首先声明两个Uri,一个保存拍照的结果,一个保存裁剪的结果:
imageuri = Uri.fromFile(createImageFile("jpg"));
cropuri = Uri.fromFile(createImageFile("temp"));
点击按钮时仅调起拍照Intent,将结果存在imageUri中
Intent intent = null;
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, ACTION_TAKE);
在接收到返回的消息后,调起裁剪Intent:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode!= Activity.RESULT_OK){
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode){
case ACTION_TAKE:
cropImage(imageuri);
break;
}
}
public void cropImage(Uri uri){
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 700);
intent.putExtra("outputY", 700);
intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, cropuri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra("noFaceDetection", true);
startActivityForResult(intent, ACTION_CROP);
}
将传进去的uri做为源数据,即被裁剪的数据,将结果存储在imageCropUri中,最后在onActivityResult中接受:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode!= Activity.RESULT_OK){
Toast.makeText(this, "失败", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode){
case ACTION_TAKE:
cropImage(imageuri);
break;
case ACTION_CROP:
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(cropuri));
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
break;
}
}
这样就可以正常将结果显示到ImageView了