项目中经常遇到从图库选择或从相机拍照的图片选择对话框的需求,这里做一个总结,方便以后参考使用。
代码片段是从一个完整项目截取部分。
1.先判斷手機是否有SD卡,若沒有彈出提示框
Boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if (!isSDPresent){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(getString(R.string.exit_dialog));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setMessage(getText(R.string.error_no_sdcard));
builder.setCancelable(false);
builder.setPositiveButton(getText(R.string.btn_yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (dlgNoSDCard != null) {
dlgNoSDCard.dismiss();
dlgNoSDCard = null;
}
}
});
if (dlgNoSDCard == null) {
dlgNoSDCard = builder.create();
}
dlgNoSDCard.show();
return;
}
2.定義選擇圖片的Uri文件路徑,用來保存選擇的圖片,從相機選擇返回的是Uri的形式的圖片
Uri mImageCaptureUri = null;
customizedFilePath();
private Uri customizedFilePath() {
//目錄名
String sDirName = "psmd/1touchmore/photo";
//文件名
String fileName = System.currentTimeMillis() + ".jpg";
//SD卡目錄
File sdDir = Environment.getExternalStorageDirectory();
//生成目錄
File theDir = new File(sdDir, sDirName);
if (!theDir.exists()) {
theDir.mkdirs();
}
//生成文件
File picFile = new File(theDir, fileName);
//返回文件路徑對應的Uri對象
mImageCaptureUri = Uri.fromFile(picFile);
return mImageCaptureUri;
}
3.從系統圖庫選擇:
Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickPhoto.setType("image/*");
//可裁剪
pickPhoto.putExtra("crop", "true");
//輸出格式
pickPhoto.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
//不需要人臉檢測
pickPhoto.putExtra("noFaceDetection", true);
// outputX,outputY 是剪裁图片的宽高
pickPhoto.putExtra("outputX", reqWidth);
pickPhoto.putExtra("outputY", reqHeight);
//aspectX aspectY 是宽高的比例
pickPhoto.putExtra("aspectX", 1);
pickPhoto.putExtra("aspectY", 1);
//縮放比例
pickPhoto.putExtra("scale", 1);
pickPhoto.putExtra("return-data", true);
try {
startActivityForResult(pickPhoto, TAKE_FROM_GALLERY);
}
catch (ActivityNotFoundException localActivityNotFoundException)
{
Log.d("Light", "Pick From Gallery Activity Not Found => " + pickPhoto.getAction());
}
4.從相機拍照:
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePicture.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// 指定调用相机拍照后照片的储存路径
takePicture.putExtra(MediaStore.EXTRA_OUTPUT, mImageCaptureUri);
takePicture.putExtra("return-data", true);
try{
startActivityForResult(takePicture, TAKE_FROM_CAMERA);
}
catch (ActivityNotFoundException e) {
Log.d("Light", "Take Pict Activity Not Found => " + takePicture.getAction());
}
5.在onActivityResult方法中判斷返回的request code分別處理
switch(requestCode) {
case TAKE_FROM_GALLERY:
//從圖庫選擇的圖片返回
try {
Bundle extras = data.getExtras();
if(extras != null ) {
//返回的裁剪后的圖片的bitmap
bmpOriginal = extras.getParcelable("data");
Runnable r = new Runnable(){
public void run(){
//重新定義寬和高設置到View
bmpLarge = getResizedBitmapToNewWH(bmpOriginal, bmpOriginal.getWidth(), bmpOriginal.getHeight());
ivChooseHeaderIcon.setImageBitmap(bmpLarge);
}
};
ivChooseHeaderIcon.post(r);
}
}
catch(Exception e)
{
Log.e("Could not save", e.toString());
}
private Bitmap getResizedBitmapToNewWH(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float aspect = (float)width / height;
float scaleWidth = newWidth;
float scaleHeight = scaleWidth / aspect;
Bitmap resizedBitmap = null;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth / width, scaleHeight / height);
resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
try {
if ((resizedBitmap.getHeight() - newHeight) >= 0) {
resizedBitmap = Bitmap.createBitmap(resizedBitmap, 0, (resizedBitmap.getHeight() - newHeight) / 2, newWidth, newHeight);
}
} catch (Exception e) {
Log.d("Light", e.toString());
}
return resizedBitmap;
}
case TAKE_FROM_CAMERA:
//從相機拍照返回的圖片調用裁剪
Intent cropIntent = new Intent("com.android.camera.action.CROP");
cropIntent.setDataAndType(mImageCaptureUri, "image/*");
cropIntent.putExtra("crop", "true");
cropIntent.putExtra("aspectX", 1);
cropIntent.putExtra("aspectY", 1);
cropIntent.putExtra("outputX", reqWidth);
cropIntent.putExtra("outputY", reqHeight);
cropIntent.putExtra("return-data", true);
cropIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
cropIntent.putExtra("noFaceDetection", true);
try{
startActivityForResult(cropIntent, TAKE_FROM_CROP);
}
catch (ActivityNotFoundException e)
{
Log.d("Light", "Cannot Call Crop Activity => " + cropIntent.getAction());
}
case TAKE_FROM_CROP:
//裁剪后的圖片 設置到View
Bundle extras = data.getExtras();
if(extras != null ) {
try {
bmpOriginal = extras.getParcelable("data");
Runnable r = new Runnable(){
public void run(){
bmpLarge = getResizedBitmapToNewWH(bmpOriginal, bmpOriginal.getWidth(), bmpOriginal.getHeight());
ivChooseHeaderIcon.setImageBitmap(bmpLarge);
}
};
ivChooseHeaderIcon.post(r);
}
catch(Exception e)
{
Log.e("Could not save", e.toString());
}
}
6.當保存數據時,保存選擇的圖片路徑
private void doSavePic(){
FileOutputStream stream;
//從圖庫和相機選擇圖片會返回bitmap對象
if (bmpOriginal != null)
{
String sLargePicPath = "";
try {
if (mImageCaptureUri != null) {
// 若不為 null,則代表是拍照片
sLargePicPath = mImageCaptureUri.getPath();
}
else {
// 取得存放照片的路徑名 - 大張
sLargePicPath = customizedFilePath().getPath();
}
stream = new FileOutputStream(sLargePicPath);
// 將圖檔縮小成 700 x 400 的規格
bmpTemp = getResizedBitmapToNewWH(bmpOriginal, 700, 400);
// 不做壓縮,直接存
bmpTemp.compress(CompressFormat.JPEG, 100, stream);
stream.flush();
stream.close();
// 取得存放照片的路徑名 - 小張
String sSmallPicPath = sLargePicPath.substring(0, sLargePicPath.indexOf(".")) + "_small.jpg";
// 將變小後的圖形回存到 SD 上
stream = new FileOutputStream(sSmallPicPath);
// 把圖型轉成小張
bmpTemp = getResizedBitmapToSquare(bmpOriginal, 200);
//壓縮比改為 90
bmpTemp.compress(CompressFormat.JPEG, 90, stream);
stream.flush();
stream.close();
// 將要存的檔案名稱,設定給 ImagePathFile
ImagePathFile = sSmallPicPath;
// 釋放 BMP 所佔的資源
bmpOriginal.recycle();
bmpTemp.recycle();
} catch (Exception e) {
Log.e("Could not save => ", e.toString());
}
}
}