Android拍照及裁剪實現
一.概述
拍照以及裁剪功能在有些專案中還是經常能遇到的,一般而言,使用拍照和裁剪功能基本上都是使用系統自帶的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了