標籤:imageview bitmap 圖片 uri
ok,這次的項目需要用到設定頭像功能,所以做了個總結,直接進入主題吧。
先說說怎麼
- 使用android內建的相機拍照然後擷取到這張照片吧
直接上代碼:
Intent intentFromCapture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);Uri imageUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory()+"/zxy/image/temp.png"));// 指定照片儲存路徑(SD卡),temp.jpg為一個臨時檔案,每次拍照後這個圖片都會被替換intentFromCapture.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);startActivityForResult(intentFromCapture,CAMERA_REQUEST_CODE);
MediaStore.ACTION_IMAGE_CAPTURE是調用系統內建的相機,有關相應功能的Action字串的請看我的另外一篇博文,《
Android開發之Intent.Action 各種Action的常見作用》,然後用MediaStore.EXTRA_OUTPUT的Action,告訴系統需要放入一個媒體檔案,那麼,這個媒體檔案放在哪裡呢?就是通過Uri告訴它的,我們把拍照後的圖片放在手機內建sd卡根目錄的zxy目錄下的image目錄下,並指定該照片的名稱為temp.png,目錄顯示為:/storage/sdcard0/zxy/image/temp.png。然後通過Uri.fromFile(File file)方法得到一個File對象的Uri,這樣,我們就把剛剛拍的照片放在了/storage/sdcard0/zxy/image目錄下。
那麼,我們怎麼得到這張圖片呢?
1、如果是我們拍照後,要直接使用這張圖片作為什麼背景圖、頭像啊等等,一般這個用的最多,我們就可以通過我們剛剛傳入的請求碼來判斷和設定這種圖片,這就需要重寫Activity的onActivityResult()方法,直接上代碼:
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode != Activity.RESULT_CANCELED) {//通過結果碼來判斷是否拍取了圖片switch (requestCode) {//通過請求碼來判斷是哪個請求的資料case IMAGE_REQUEST_CODE://.............break;case CAMERA_REQUEST_CODE://需要注意的是這裡直接返回的圖片資訊是通過Intent data傳遞的,data.getData()得到該圖片的uri的,然後通過該圖片的uri來做相應的事//.............break;}}}2、如果只是單純的照相、我們可以通過這個方法來使用,取出照片可以通過BitmapFactory.decodeFile(String pathName)傳入一個圖片所在路徑即可得到該圖片,或者通過先得到該圖片的輸入資料流,然後通過BitmapFactory.decodeStream(InputStream is)來獲得該圖片.....等等,方法反正有好多的。
順便普及一下android內部的各種方法得到的目錄:
1、Environment.getExternalStorageDirectory()得到的目錄為:/storage/sdcard0
2、Environment.getDataDirectory()得到的目錄為:/data
3、Environment.getRootDirectory()得到的目錄為:/system
我們的app應用都是安裝在/data/data目錄下的,而一般的資料目錄我們一般建立在內建sd卡/storage/sdcard0目錄下,一般都是以這個app的名稱建立檔案夾,再建立其它目錄,一般私密的資料我們可以建立在app的目錄下,即/data/data/應用程式套件名/建立的私密資料目錄。
- 選擇相簿中的圖片來使用選中的圖片設定頭像或背景,直接上代碼:
Intent intentFromGallery = new Intent(Intent.ACTION_GET_CONTENT);intentFromGallery.setType("image/*");startActivityForResult(intentFromGallery,IMAGE_REQUEST_CODE);Intent.ACTION_GET_CONTENT是說明這個Aciton是用來得到一個內容的,那麼這個內容是什麼呢?就是通過setType()來進行過濾的。然後重寫Activity的onActivityResult()方法通過data.getData()得到選中圖片的uri,然後可以通過這兩種方式獲得選中的圖片:
1、通過
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
來得到bitmap對象。
2、通過uri得到對應的路徑,通過路徑得到File檔案對象或者io流來執行各個操作。
// 得到圖片路徑private String getImgPath(Intent data) {if (data != null) {Uri uri = data.getData();String[] pojo = { MediaStore.Images.Media.DATA };Cursor cursor = this.getContentResolver().query(uri, pojo, null,null, null);String path = null;if (cursor != null) {int columnIndex = cursor.getColumnIndex(pojo[0]);cursor.moveToFirst(); // 將游標移至開頭第一個位置path = cursor.getString(columnIndex);cursor.close();}return path;} else {Toast.makeText(UserLogin.this, "你沒有選擇圖片", Toast.LENGTH_SHORT).show();return null;}}
- 怎麼把拍照後的圖片或者在相簿選取的圖片先剪下然後再用剪下後的圖片呢?通過傳一個Uri或者路徑,就可以對該圖片進行剪下了。
// 裁剪圖片public void startPhotoZoom(Uri uri) {Intent intent = new Intent("com.android.camera.action.CROP");//發起剪下動作intent.setDataAndType(uri, "image/*");//設定剪下圖片的uri和類型intent.putExtra("crop", "true");//剪下動作的訊號intent.putExtra("aspectX", 1);//x和y是否等比縮放intent.putExtra("aspectY", 1);intent.putExtra("outputX", 320);intent.putExtra("outputY", 320);//剪下後圖片的尺寸intent.putExtra("return-data", true);//是否把剪下後的圖片通過data返回intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());//圖片的輸出格式 intent.putExtra("noFaceDetection", true); //關閉臉部辨識//設定剪下的圖片儲存位置Uri cropUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory().getPath() + "/zxy/image/crop.png"));intent.putExtra(MediaStore.EXTRA_OUTPUT,cropUri);startActivityForResult(intent, RESULT_REQUEST_CODE);}
剪下動作其實有好多參數的,這裡給出一下:
Exta Options Table for image/* crop:
| 附加選項 |
資料類型 |
描述 |
| crop |
String |
發送裁剪訊號 |
| aspectX |
int |
X方向上的比例 |
| aspectY |
int |
Y方向上的比例 |
| outputX |
int |
裁剪區的寬 |
| outputY |
int |
裁剪區的高 |
| scale |
boolean |
是否保留比例 |
| return-data |
boolean |
是否將資料保留在Bitmap中返回 |
| data |
Parcelable |
相應的Bitmap資料 |
| circleCrop |
String |
圓形裁剪地區? |
| MediaStore.EXTRA_OUTPUT ("output") |
URI |
將URI指向相應的file:///...,詳見程式碼範例 |
| outputFormat |
String |
輸出格式,一般設為Bitmap格式:Bitmap.CompressFormat.JPEG.toString() |
| noFaceDetection |
boolean |
是否取消Face Service功能 |
這些參數可以隨意匹配,這裡我們就裁剪從相簿轉過來的圖片,當然也可以單獨做一個剪下功能,只需要穿一個uri既可。
這裡圖片剪下後,通過請求碼來在onActivityResult()中判斷,然後傳過來一個Intent 類型的data資料,我們可以通過剛剛設定的剪下後圖片的位置得到這張剪下後的圖片,也可以通過uri得到,或者轉換為路徑得到,或者直接通過
Bundle extras = data.getExtras();if (extras != null) {Bitmap photo = extras.getParcelable("data");Drawable drawable = new BitmapDrawable(null, photo);}來得到這張圖片,這裡我們就用這個方法來得到的,較為簡便。
【注意】我們在使用剪下圖片的時候,通常我們設定屬性只能設定一些比較小的值,像intent.putExtra("outputX", 320);intent.putExtra("outputY", 320);剪下後圖片的尺寸不能設定為過大,經測試到640就會出現卡住的現象,為什麼呢?原因是在於Intent 的data域最大傳遞的值的大小約為1M,所以圖片的BITMAP當超過1M時就會失敗。通常我們只是設定頭像可以用這個方法,那麼如果我們要剪下顯示一些比較大的圖片呢?怎麼做呢?
該方法就是先設定為return-data設為false,不從data域擷取圖片,而是越過這個橋樑,通過我們剛剛在剪下圖片後設定的路徑目錄和名稱來單獨擷取這個圖片,就可以完美顯示了。如果不設定return-data為false,那麼就會預設通過data返回,從而造成卡住現像。
return-data:是將結果儲存在data中返回,在onActivityResult中,直接調用intent.getdata()就可以擷取值了,這裡設為fase,就是不讓它儲存在data中
MediaStore.EXTRA_OUTPUT:由於我們不讓它儲存在Intent的data域中,但我們總要有地方來儲存我們的圖片,這個參數就是轉移儲存地址的,對應Value中儲存的URI就是指定的儲存地址。
android拍照獲得圖片及獲得圖片後剪下設定到ImageView