android调用原生剪裁界面裁剪图片
最近做一个用户上传图像的功能,本来以为很简单的,就是拍照或从相册得到图片,然后调用系统自带的裁剪功能裁剪下就可以了,但是真正写的时候发现还是有些坑的。主要的问题是裁剪时参数一定要设置对,要不然就会得不到裁剪后的图片。还有就是不管是拍照还是裁剪,最好选择将图片保存到一个临时目录,不要选择直接在intent的data中直接返回bitmap对象。
直接上代码了,下面的类中实现了从相册和拍照得到图片,并剪裁图片的功能。
代码在5.0(三星),6.0(nexus)的机器上测试是没有问题的,如果大家发现有什么问题欢迎留言指正。
/**
* Created by lee on 2016/9/19.
*/
public class ImageUploadFragment extends Fragment {
private ImageView headView;
private View rootView;
private static final int REQUEST_CODE_SELECT_PHOTO = 1;
private static final int REQUEST_CODE_TAKE_PHOTO = 2;
private static final int REQUEST_CODE_CUT_PHOTO = 3;
private String IMAGE_NAME = "temp.jpeg";
private String IMAGE_FILE_URI_PATH = "";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_image_upload, container, false);
return rootView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
headView = (ImageView) rootView.findViewById(R.id.image);
headView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showChooseImageDialog();
}
});
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
IMAGE_FILE_URI_PATH = getActivity().getExternalCacheDir().getPath();
}
private void showChooseImageDialog() {
CharSequence[] items = {"相册", "相机"};
new AlertDialog.Builder(getActivity())
.setTitle("选择图片来源")
.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
chooseImg();
} else {
takePhoto();
}
}
})
.create().show();
}
private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getTempPhotoFileUri());
startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
}
private void chooseImg() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_PICK);//Pick an item from the data
intent.setType("image/*");//从所有图片中进行选择
startActivityForResult(intent, REQUEST_CODE_SELECT_PHOTO);
}
private Uri getTempPhotoFileUri() {
File file = new File(IMAGE_FILE_URI_PATH);
if (!file.exists()) {
file.mkdirs();
}
File imageFile = new File(file, IMAGE_NAME);
return Uri.fromFile(imageFile);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_CODE_SELECT_PHOTO) {
if (data != null) {
Uri uri = data.getData();
crop(uri, getTempPhotoFileUri());
}
} else if (requestCode == REQUEST_CODE_TAKE_PHOTO) {
crop(getTempPhotoFileUri(), getTempPhotoFileUri());
} else if (requestCode == REQUEST_CODE_CUT_PHOTO) {
handleCropImg(data);
try {
deleteFile(getTempPhotoFileUri().getPath());
} catch (Exception e) {
e.printStackTrace();
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void handleCropImg(Intent data) {
if (data != null) {
//有的手机返回的data中没有任何数据,可能和crop时Intent中使用了MediaStore.EXTRA_OUTPUT有关,所以直接从保存图片的uri中获取图片
// Uri uri = data.getData();
Bitmap bitmap = getBitmapFromUri(getTempPhotoFileUri());
if (bitmap != null) {
headView.setImageBitmap(bitmap);
}
}
}
public Bitmap getBitmapFromUri(Uri uri) {
try {
// 读取uri所在的图片
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), uri);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 剪切图片
*
* @param uri 原始图片的uri
*/
private void crop(Uri uri, Uri tempPhotoUri) {
// 裁剪图片意图
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", 250);//裁切的宽度
intent.putExtra("outputY", 250);//裁切的高度
intent.putExtra("scale", true);//支持缩放
intent.putExtra("return-data", false);//剪切的图片不直接返回,返回uri,否则6.0可能会返回null
//这里是剪切后图片保存的文件地址,加了这行,可能有些手机返回的intent是空的,所以最好直接使用这个uri获取剪切后的图片
intent.putExtra(MediaStore.EXTRA_OUTPUT, tempPhotoUri);
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//裁切成的图片的格式
intent.putExtra("noFaceDetection", true); // no face detection
startActivityForResult(intent, REQUEST_CODE_CUT_PHOTO);
}
private boolean deleteFile(String filepath) {
boolean wasDeleted = false;
try {
File file = new File(filepath);
wasDeleted = file.delete();
} catch (Exception e) {
e.printStackTrace();
}
return wasDeleted;
}
}