Android之圖片選擇與裁剪
阿新 • • 發佈:2019-01-23
對於現在的應用來說,基本都有使用者模組,當然也就涉及到了使用者頭像的修改問題。修改頭像我們一般採用兩種方式:呼叫系統相機進行拍照或從相簿中選擇圖片進行上傳。但是由於Rom定製市場的混亂,導致了出現此問題在解決時需要重點考慮了相容性,下面給出一種通用解決方案。
啟動相機進行拍照
需要注意的是,Android系統為了防止傳送原圖出現OOM,拍照後預設返回的是縮圖,為了解決這種問題,我們在啟動相機的時候要先設定照片的儲存路徑,即傳遞MediaStore.EXTRA_OUTPUT引數,這樣拍照完成後我們就可以根據之前設定的路徑讀取原圖了。
1 2 3 4 5 6 |
// 設定圖片的輸出路徑 File file = new File(Environment.getExternalStorageDirectory() + "/temp_icon.jpg"); |
開啟相簿選擇圖片
選擇圖片操作其實沒什麼難度,選擇完成後預設返回的就是圖片的儲存路徑。
1 2 3 |
Intent intent = new Intent(Intent.ACTION_PICK, null); |
裁剪圖片
和拍照的情況一樣,Android為了防止傳送大圖片出現OOM,在截圖的過程中預設傳遞的也是縮圖,這樣裁減後的圖片會非常模糊。所以採用URi的方式傳遞來原圖的路徑。需要注意的是,如果傳遞原圖,那麼拍照時需要設定照片的輸出路徑,也就是在呼叫相機時傳遞MediaStore.EXTRA_OUTPUT引數,同時為了防止某些手機預設傳遞原圖的問題(如小米4),在傳遞大圖片時將return-data置為false;對於某些手機或平板,輸入Uri和輸出Uri不能相等,否則裁減後的圖片大小變為0kb,如平板Teclast P80h.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * 裁減圖片操作 * @param uri */ private void startCropImage(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); // 使圖片處於可裁剪狀態 intent.putExtra("crop", "true"); // 裁剪框的比例(根據需要顯示的圖片比例進行設定) intent.putExtra("aspectX", 3); intent.putExtra("aspectY", 2); // 讓裁剪框支援縮放 intent.putExtra("scale", true); // 裁剪後圖片的大小(注意和上面的裁剪比例保持一致) intent.putExtra("outputX", AndroidPlatformUtil.dpToPx(this, 120)); intent.putExtra("outputY", AndroidPlatformUtil.dpToPx(this, 80)); // 傳遞原圖路徑 File cropFile = new File(Environment.getExternalStorageDirectory() + "crop_image.jpg"); cropImageUri = Uri.fromFile(cropFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, cropImageUri); // 設定裁剪區域的形狀,預設為矩形,也可設定為原形 //intent.putExtra("circleCrop", true); // 設定圖片的輸出格式 intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); // return-data=true傳遞的為縮圖,小米手機預設傳遞大圖,所以會導致onActivityResult呼叫失敗 intent.putExtra("return-data", false); // 是否需要人臉識別 intent.putExtra("noFaceDetection", true); startActivityForResult(intent, REQUEST_CODE_CROP_IMAGE); } |
獲取傳遞的圖片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if(intent != null) { switch (requestCode) { // 將拍攝的照片進行裁剪(注意,這裡需要傳遞的是照片的路徑,而不是intent.getData(), 因為intent.getData()返回的是縮圖的資料) case REQUEST_CODE_TAKE_PHOTO: startCropImage(iconUri); break; // 將選擇的圖片進行裁剪 case REQUEST_CODE_CHOOSE_IMAGE: if (intent.getData() != null) { iconUri = intent.getData(); startCropImage(iconUri); } break; // 將裁剪後的圖片進行上傳 case REQUEST_CODE_CROP_IMAGE: // 上傳圖片操作 break; default: break; } } else { // 解決某些手機intent為空的情況 if (requestCode == REQUEST_CODE_TAKE_PHOTO && iconUri != null) { startCropImage(iconUri); } } } |
總結
通過上面的四步,圖片的選擇與裁剪就完成了。總的來說,需要注意的只有一點,無論是拍照還是選選擇圖片到裁剪的過程,只有傳遞圖片的路徑才能從根本上實現此問題。否則將出現各種相容性問題。還有一點需要提醒的是:裁剪是真正決定所要展示圖片的比例和大小的。