文章目錄
- 前言
- 一、獲取圖片的方式
- 1.使用相機方式即時拍照
- 2.使用相冊方式選擇照片
- 二、獲取到選擇的照片進行裁剪
- 1.獲取到相機拍攝到的照片
- 2.獲取到選擇的照片
- 3.呼叫裁剪后回傳
- 4.呼叫系統裁剪圖片后回傳
- 5.保存裁剪后回傳的圖片到指定檔案
- 三、注意事項
- 總結
前言
Android提供了原生的裁剪方式,并輸出裁剪后的資源到相應的目錄,主要有兩種方式,下面我們來看看這兩種方式,由于Android10提出磁區儲存,我們這里為了方便暫不使用磁區儲存,通過使用 android:requestLegacyExternalStorage="true"這樣的配置來使用原有的存盤方式,另外Android7.0對限制了對訪問邏輯需要以Uri的方式,需要配置Provider并且創建uri使用FileProvider.getUriForFile(),
一、獲取圖片的方式
1.使用相機方式即時拍照
/**
* 從相機獲取圖片
*/
private void getPicFromCamera() {
//用于保存呼叫相機拍照后所生成的檔案
tempFile = new File(Environment.getExternalStorageDirectory().getPath(), System.currentTimeMillis() + ".jpg");
//跳轉到呼叫系統相機
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//判斷版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //如果在Android7.0以上,使用FileProvider獲取Uri
intent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(MainActivity.this,
this.getPackageName() + ".fileprovider", tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
} else { //否則使用Uri.fromFile(file)方法獲取Uri
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
}
startActivityForResult(intent, CAMERA_REQUEST_CODE);
}
2.使用相冊方式選擇照片
/**
* 從相冊獲取圖片
*/
private void getPicFromAlbm() {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, ALBUM_REQUEST_CODE);
}
二、獲取到選擇的照片進行裁剪
1.獲取到相機拍攝到的照片
代碼如下:
case CAMERA_REQUEST_CODE: //呼叫相機后回傳
if (resultCode == RESULT_OK) {
//用相機回傳的照片去呼叫剪裁也需要對Uri進行處理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Uri contentUri = FileProvider.getUriForFile(MainActivity.this,
this.getPackageName() + ".fileprovider", tempFile);
cropPhoto(contentUri);
} else {
cropPhoto(Uri.fromFile(tempFile));
}
}
break;
2.獲取到選擇的照片
代碼如下:
case ALBUM_REQUEST_CODE: //呼叫相冊后回傳
if (resultCode == RESULT_OK) {
Uri uri = intent.getData();
cropPhoto(uri);
}
break;
3.呼叫裁剪后回傳
代碼如下:
case CROP_REQUEST_CODE: //呼叫剪裁后回傳
if (intent == null) {
return;
}
Bundle bundle = intent.getExtras();
if (bundle != null) {
//在這里獲得了剪裁后的Bitmap物件,可以用于上傳
Bitmap image = bundle.getParcelable("data");
//設定到ImageView上
mHeader_iv.setImageBitmap(image);
//也可以進行一些保存、壓縮等操作后上傳
// String path = saveImage("head_output", image);
// Log.d("dsadsadsa",path);
}
break;
4.呼叫系統裁剪圖片后回傳
代碼如下:
/**
* 裁剪圖片
* * https://www.jianshu.com/p/3b92a0e30828
*/
private void cropPhoto(Uri uri) {
//在7.0以上系統裁剪完畢之后,會提示“無法保存經過裁剪的圖片”
//這是因為,我們在7.0以上跨檔案傳輸uri時候,需要用FileProvider,但是這里需要用
//Uri.fromFile(file)生成的,而不是使用FileProvider.getUriForFile
//intent.putExtra("set-as-wallpaper",true); 默認是false,當你弄成true的時候,你就會發現打開不是裁剪的,而是設定為壁紙的操作,
// intent.putExtra("return-data", true);下面就可以獲取到該bitmap
// if (data != null && data.getParcelableExtra("data") != null) {
// mStream = new ByteArrayOutputStream();
// mBitmap = data.getParcelableExtra("data");
// mBitmap.compress(Bitmap.CompressFormat.PNG, 100, mStream);
// /**圖片可以應用了*/
// /**接下來就是上傳到服務器*/
// File files = creatFile(mBitmap);//變成檔案
// ...后續根據需要來...
//}
Uri contentUri = Uri.fromFile(new File(getPhotoPath()));
Intent intent = new Intent("com.android.camera.action.CROP");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//Android 7.0需要臨時添加讀取Url的權限, 添加此屬性是為了解決:呼叫裁剪框時候提示:圖片無法加載或者加載圖片失敗或者無法加載此圖片
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setDataAndType(uri, "image/*");
intent.putExtra("crop", "true");//發送裁剪信號,去掉也能進行裁剪
intent.putExtra("scale", true);// 設定縮放
intent.putExtra("scaleUpIfNeeded", true);// 去黑邊
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
//上述兩個屬性控制裁剪框的縮放比例,
//當用戶用手拉伸裁剪框時候,裁剪框會按照上述比例縮放,
intent.putExtra("outputX", 300);//屬性控制裁剪完畢,保存的圖片的大小格式,
intent.putExtra("outputY", 300);//你按照1:1的比例來裁剪的,如果最后成像是800*400,那么按照2:1的樣式保存,
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString());//輸出裁剪檔案的格式
intent.putExtra("return-data", true);//是否回傳裁剪后圖片的Bitmap
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);//設定輸出路徑
startActivityForResult(intent, CROP_REQUEST_CODE);
}
5.保存裁剪后回傳的圖片到指定檔案
###如果裁剪時沒有設定輸出路徑,并且回傳Bitmap這時就可以輸出Bitmap到指定檔案
代碼如下:
public String saveImage(String name, Bitmap bmp) {
File appDir = new File(指定路徑);
if (!appDir.exists()) {
appDir.mkdir();
}
String fileName = name + ".jpg";
File file = new File(appDir, fileName);
try {
FileOutputStream fos = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
return file.getAbsolutePath();
} catch (IOException e) {
Log.d("dsadsadsa", e.getLocalizedMessage());
e.printStackTrace();
}
return null;
}
三、注意事項
其中有以下幾點需要注意:
outputX和outputY不能為0,有些手不支持為0的情況,
outputX和outputY不能設定太大,我的demo中僅僅設定了300,但部分手機設定600之后系統層出現OOM現象,
return-data屬性值只能是true,否則不會回傳資料,
URI物件的獲取必須是以下代碼
Uri.fromFile(new File(crop_path))
如果寫成
Uri.parse(crop_path)
則可能沒有資料回傳,
總結
以上就是關于Android系統裁剪的內容,如有錯誤,煩請指正!!!
參考優秀文章:
- https://www.jianshu.com/p/3b92a0e30828
- https://www.jianshu.com/p/c6271f5dad46
- https://links.jianshu.com/go?to=https%3A%2F%2Fsegmentfault.com%2Fq%2F1010000005070720%2Fa-1020000005071373
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/242413.html
標籤:其他
下一篇:如何基于MFC制作簡易繪圖軟體
