技術(shù)員聯(lián)盟提供win764位系統(tǒng)下載,win10,win7,xp,裝機(jī)純凈版,64位旗艦版,綠色軟件,免費(fèi)軟件下載基地!

當(dāng)前位置:主頁 > 教程 > 服務(wù)器類 >

Android獲取照片、裁剪圖片、壓縮圖片教程

來源:技術(shù)員聯(lián)盟┆發(fā)布時(shí)間:2017-10-28 00:17┆點(diǎn)擊:

在做上一個(gè)項(xiàng)目時(shí)深深受到了圖片上傳的苦惱。圖片上傳主要分為兩個(gè)部分,首先要獲取圖片,而獲取圖片可以分為從文件獲取或者拍照獲取。第二個(gè)部分才是上傳圖片,兩個(gè)部分都是走了不少彎路。由于Android系統(tǒng)的碎片化比較嚴(yán)重,我們可能出現(xiàn)在第一臺(tái)機(jī)子上能獲取圖片,但是換一個(gè)機(jī)子就不能獲取圖片的問題,并且在Android6.0,7.0之后也要做一定的適配,這樣對于開發(fā)者來說,無疑很蛋疼。由于也是初學(xué)者,很多東西沒有考慮到,適配起來也是有點(diǎn)難度的。

這幾天也是從github上找到了一個(gè)庫(地址在這TakePhoto),經(jīng)過簡單的學(xué)習(xí)之后,發(fā)現(xiàn)用起來還是蠻簡單的,并且在不同機(jī)型之間都能達(dá)到同樣的效果。更重要的是可以根據(jù)不同配置達(dá)到不同的效果

接下來看下用法

獲取圖片

1) 獲取TakePhoto對象

一) 通過繼承的方式

繼承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。
通過getTakePhoto()獲取TakePhoto實(shí)例進(jìn)行相關(guān)操作。
重寫以下方法獲取結(jié)果

void takeSuccess(TResult result); void takeFail(TResult result,String msg); void takeCancel();

這種方法使用起來雖然簡單,但是感覺定制性不高,必須繼承指定的Activity,而 有時(shí)我們已經(jīng)封裝好了BaseActivity,不想再改了。有時(shí)候通過繼承無法滿足實(shí)際項(xiàng)目的需求。

二) 通過組裝的方式去使用

實(shí)現(xiàn)TakePhoto.TakeResultListener,InvokeListener接口。
在 onCreate,onActivityResult,onSaveInstanceState方法中調(diào)用TakePhoto對用的方法。
重寫onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults),添加如下代碼。

@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); //以下代碼為處理Android6.0、7.0動(dòng)態(tài)權(quán)限所需 TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults); PermissionManager.handlePermissionsResult(this,type,invokeParam,this); }

重寫TPermissionType invoke(InvokeParam invokeParam)方法,添加如下代碼:

@Override public TPermissionType invoke(InvokeParam invokeParam) { TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod()); if(TPermissionType.WAIT.equals(type)){ this.invokeParam=invokeParam; } return type; }

添加如下代碼獲取TakePhoto實(shí)例:

/** * 獲取TakePhoto實(shí)例 * @return */ public TakePhoto getTakePhoto(){ if (takePhoto==null){ takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this)); } return takePhoto; }

2)自定義UI

不僅可以對于參數(shù)自定義,也可以對于UI的自定義,比如自定義相冊,自定義Toolbar, 自定義狀態(tài)欄,自定義提示文字,自定義裁切工具(需要使用自帶的TakePhoto裁剪才行)。

3)通過TakePhoto對象獲取圖片

支持從相冊獲取,也支持拍照,相關(guān)Api

* 從相機(jī)獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options); /** * 從相冊中獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options); /** * 從文件中獲取圖片并裁剪 * @param outPutUri 圖片裁剪之后保存的路徑 * @param options 裁剪配置 */ void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options); /** * 圖片多選,并裁切 * @param limit 最多選擇圖片張數(shù)的限制 * @param options 裁剪配置 * */ void onPickMultipleWithCrop(int limit, CropOptions options);

4)裁剪配置

CropOptions 用于裁剪的配置類,可以對圖片的裁剪比例,最大輸出大小,以及是否使用TakePhoto自帶的裁剪工具進(jìn)行裁剪等,進(jìn)行個(gè)性化配置。

壓縮圖片 onEnableCompress(CompressConfig config,boolean showCompressDialog)

指定壓縮工具 takePhoto里面自帶壓縮算法,也可以通過第三方的Luban進(jìn)行壓縮

對于TakePhoto的二次封裝

封裝是對第二種方法的封裝,主要參考了第一種的思想封裝的。
關(guān)于TakePhoto的庫代碼全部封裝到一個(gè)TakePhotoUtil工具類中,看代碼:

public class TakePhotoUtil implements TakePhoto.TakeResultListener, InvokeListener { private static final String TAG = TakePhotoUtil.class.getName(); private TakePhoto takePhoto; private InvokeParam invokeParam; private Activity activity; private Fragment fragment; public TakePhotoUtil(Activity activity){ this.activity = activity; } public TakePhotoUtil(Fragment fragment){ this.fragment = fragment; } /** * 獲取TakePhoto實(shí)例 * @return */ public TakePhoto getTakePhoto(){ if (takePhoto==null){ takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(activity,this)); } return takePhoto; } public void onCreate(Bundle savedInstanceState){ getTakePhoto().onCreate(savedInstanceState); } public void onSaveInstanceState(Bundle outState){ getTakePhoto().onSaveInstanceState(outState); } public void onActivityResult(int requestCode, int resultCode, Intent data){ getTakePhoto().onActivityResult(requestCode, resultCode, data); } public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { PermissionManager.TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults); PermissionManager.handlePermissionsResult(activity,type,invokeParam,this); } /** * * @param result */ @Override public void takeSuccess(TResult result) { if(listener != null){ listener.takeSuccess(result); } // deleteCachePic(); } @Override public void takeFail(TResult result, String msg) { if(listener != null){ listener.takeFail(result, msg); } // deleteCachePic(); } @Override public void takeCancel() { if(listener != null){ listener.takeCancel(); } } public void deleteCachePic(){ File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/"); if(!file.exists()) return; File[] files = file.listFiles(); for (File f: files) { f.delete(); } } public interface TakePhotoListener{ void takeSuccess(TResult result); void takeFail(TResult result, String msg); void takeCancel(); } public TakePhotoListener listener; public void setTakePhotoListener(SimpleTakePhotoListener listener){ this.listener = listener; } public static class SimpleTakePhotoListener implements TakePhotoListener{ @Override public void takeSuccess(TResult result) { } @Override public void takeFail(TResult result, String msg) { } @Override public void takeCancel() { } } @Override public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) { PermissionManager.TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(activity),invokeParam.getMethod()); if(PermissionManager.TPermissionType.WAIT.equals(type)){ this.invokeParam=invokeParam; } return type; } /** * * @param select_type */ public void takePhoto(Select_type select_type, SimpleTakePhotoListener listener){ takePhoto(select_type, null, listener); } public void takePhoto(Select_type select_type, PhotoConfigOptions cropOptions, SimpleTakePhotoListener listener){ if (takePhoto == null){ Toast.makeText(activity, "請先開啟照片功能", Toast.LENGTH_SHORT).show(); return; } setTakePhotoListener(listener); if(cropOptions == null){ cropOptions = new PhotoConfigOptions(); } cropOptions.configCompress(); //壓縮配置 cropOptions.configTakePhoto(); //拍照配置 File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/"+System.currentTimeMillis() + ".jpg"); if (!file.getParentFile().exists())file.getParentFile().mkdirs(); Uri imageUri = Uri.fromFile(file); switch (select_type){ case PICK_BY_SELECT: //從相冊獲取 if(cropOptions.limit > 1){ if(cropOptions.crop == true){ takePhoto.onPickMultipleWithCrop(cropOptions.limit, cropOptions.getCropOptions()); }else { takePhoto.onPickMultiple(cropOptions.limit); } } if(cropOptions.chooseFromFile){ if(cropOptions.crop == true){ takePhoto.onPickFromDocumentsWithCrop(imageUri, cropOptions.getCropOptions()); }else { takePhoto.onPickFromDocuments(); } }else { if(cropOptions.crop == true){ takePhoto.onPickFromGalleryWithCrop(imageUri, cropOptions.getCropOptions()); }else { takePhoto.onPickFromGallery(); } } break; case PICK_BY_TAKE: //拍照獲取 if(cropOptions.crop == true){ takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions.getCropOptions()); }else { takePhoto.onPickFromCapture(imageUri); } break; default: break; } } /** * 圖片的裁剪配置選項(xiàng)內(nèi)部類 */ public class PhotoConfigOptions{ //裁剪配置 private boolean crop = true; //是否裁剪 private boolean withWonCrop = true; //是否采用自帶的裁剪工具,默認(rèn)選取第三方的裁剪工具 private boolean cropSize = true; //尺寸還是比例 //壓縮配置 private boolean useOwnCompressTool = true; //使用自帶的壓縮工具 private boolean isCompress = true; //是否壓縮 private boolean showProgressBar = true; //顯示壓縮進(jìn)度條 // private private int maxSize = 102400; //選擇圖片配置 private boolean useOwnGallery = true; //選擇使用自帶的相冊 private boolean chooseFromFile = false; //從文件獲取圖片 private int limit = 1; //選擇最多圖片的配置,選擇多張圖片會(huì)自動(dòng)切換到TakePhoto自帶相冊 //其它配置 private boolean savePic = true; //選擇完之后是否保存圖片 private boolean correctTool = false; //糾正拍照的照片旋轉(zhuǎn)角度 private int height = 800; private int width = 800; /** * 裁剪相關(guān)配置 * @return */ public CropOptions getCropOptions(){ if(crop == false) return null; CropOptions.Builder builder = new CropOptions.Builder(); if(cropSize){ builder.setOutputX(width).setOutputY(height); }else { builder.setAspectX(width).setAspectY(height); } builder.setWithOwnCrop(withWonCrop); //默認(rèn)采用第三方配置 return builder.create(); } /** * 圖片壓縮相關(guān)配置 */ public void configCompress(){ if(isCompress == false) { takePhoto.onEnableCompress(null, false); return; } CompressConfig config; if(useOwnCompressTool){ config = new CompressConfig.Builder() .setMaxSize(maxSize) .setMaxPixel(width>height?width:height) .enableReserveRaw(savePic) .create(); }else { LubanOptions options = new LubanOptions.Builder() .setMaxHeight(height) .setMaxWidth(maxSize) .create(); config = CompressConfig.ofLuban(options); config.enableReserveRaw(savePic); } takePhoto.onEnableCompress(config, showProgressBar); } public void configTakePhoto(){ TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder(); if(useOwnGallery){ builder.setWithOwnGallery(true); } if(correctTool){ builder.setCorrectImage(true); } takePhoto.setTakePhotoOptions(builder.create()); } public void setCrop(boolean crop) { this.crop = crop; } public void setWithWonCrop(boolean withWonCrop) { this.withWonCrop = withWonCrop; } public void setCropSize(boolean cropSize) { this.cropSize = cropSize; } public void setUseOwnCompressTool(boolean useOwnCompressTool) { this.useOwnCompressTool = useOwnCompressTool; } public void setCompress(boolean compress) { isCompress = compress; } public void setShowProgressBar(boolean showProgressBar) { this.showProgressBar = showProgressBar; } public void setMaxSize(int maxSize) { this.maxSize = maxSize; } public void setUseOwnGallery(boolean useOwnGallery) { this.useOwnGallery = useOwnGallery; } public void setChooseFromFile(boolean chooseFromFile) { this.chooseFromFile = chooseFromFile; } public void setLimit(int limit) { this.limit = limit; } public void setSavePic(boolean savePic) { this.savePic = savePic; } public void setCorrectTool(boolean correctTool) { this.correctTool = correctTool; } public void setHeight(int height) { this.height = height; } public void setWidth(int width) { this.width = width; } } /** * 照片獲取方式, 從相冊獲取或拍照處理 */ public enum Select_type{ PICK_BY_SELECT, PICK_BY_TAKE } }

封裝了一個(gè)BaseTakePhotoActivity,里面的代碼如下: