《Android三方庫--TakePhoto》

寫在前面

  剛開始寫安卓的時候,總是希望自己能夠親自實現某個功能,認為只有都是自己寫出來的才會學到東西。雖然
有學長跟自己說要多利用Github,但是我卻完全沒有Get到學長的意思,以為Github只是用來看別人的代碼,學習
某個解決方案的。其實不然,Github很重要的一個用處就是上面有許多很優美的封裝過的三方庫,只需要簡單的幾
行代碼就可以實現很好的效果。一開始的時候也完全沒必要糾結于自己是不是完全能看懂某個三方庫的代碼,大家
都是從會用開始,然后到看懂,再到自己“造輪子”的。
  經過了接近一年的學習,也不可避免的接觸了許多優秀的三方庫,以后將逐步分享給大家,今天要跟大家分享
是TakePhoto.

正菜

名稱:TakePhoto
TakePhoto Github地址:https://github.com/crazycodeboy/TakePhoto
應用實例 Github地址:https://github.com/ZhangRui111/BlogLibsTakePhoto

應用場景

但凡一個最終會上線的App,基本都會有上傳用戶頭像的模塊。這里便會涉及到從相冊中選取用戶頭像、通過拍照獲取頭像、裁剪、壓縮等功能。網上有許多博客都寫到了這一功能的代碼實現,有些的確有效,有些卻無法正確返回結果。
  自己實現這一模塊主要由以下難點:
  ①. 返回的照片過大容易造成 OOM。
  ②. 安卓4.4系統作為分水嶺,4.4以上的系統返回的圖片Uri是封裝過的,并不是圖片真實的Uri,例如:

Android4.4以前獲取的uri的字符串是“content://media/external/image/media”格式的,而4.4以后變成"file:///sdcard/mysong.mp3"格式

③. Android系統的碎片化
  由于Android系統的開放性帶來的碎片化問題幾乎是從始至終會貫穿于開發過程的,而且一直沒有很好的解決方案。尤其是國內的手機廠商對于ROM的深度定制更是給程序員帶來了噩夢般的苦惱。經常是在一部手機上完全沒有問題的代碼,換一部手機,即使是Android版本相同,手機廠商不同也可能導致代碼的崩潰,唉,說多了都是淚啊, -_-|||
  ④. ...
  我也是在開發的過程中飽嘗了“碎片化”、OOM等的心酸后,才嘗試了三方庫,不得不說,Github上優秀的三方庫大都能夠很好的處理碎片化問題,畢竟只是針對某一個功能點進行適配性維護的代價還是可以承受的。

TakePhoto簡介

  • TakePhoto是一款用于在Android設備上獲取照片(拍照或從相冊、文件中選擇)、裁剪圖片、壓縮圖片的開源工具庫,目前最新版本4.0.3
  • 支持通過相機拍照獲取圖片
    支持從相冊選擇圖片
    支持從文件選擇圖片
    支持批量圖片選取
    支持圖片壓縮以及批量圖片壓縮
    支持圖片裁切以及批量圖片裁切
    支持照片旋轉角度自動糾正
    支持自動權限管理(無需關心SD卡及攝像頭權限等問題)
    支持對裁剪及壓縮參數個性化配置
    提供自帶裁剪工具(可選)
    支持智能選取及裁剪異常處理
    支持因拍照Activity被回收后的自動恢復
    支持Android7.0
    +支持多種壓縮工具
    +支持多種圖片選擇工具

哈哈,功能還是很強大的,而且,更重要的是,使用也很簡單,真是Android程序狗的福音!話不多說,基礎用法先來一遍。

TakePhoto的使用

  1. 引入三方庫依賴(安裝)

相信有許多像我一樣剛剛上手Android程序開發的編程菜鳥并不是不想用三方庫,而是苦于在沒有人指導的情況下對于如何使用一個三方庫不知所云。下面我就根據我走過的彎路介紹下引入三方庫依賴的方法,老司機發車咯,新手刷卡上車,其他老司機自動跳過即可,滴滴滴——

以AndroidStudio為例,安裝三方庫一般有三種方案:

  • build.gradle文件中添加一行或者幾行說明,一般是在dependencies{...}中添加。這種方案最為常見,也最為方便,如下圖所示

    compile 'com.jph.takephoto:takephoto_library:4.0.3'即為TakePhoto的安裝。之后只需要重新更新下build.gradle文件,等待工程下載相關依賴即可大功告成了!
    更新方式有兩個:
    ①:點擊圖中紅圈圈中按鈕

    ②:一旦build.gradle文件發生改動后,AS都會主動提示更新,點擊sync now 即可

這里要注意,一個Android工程里會有兩個build.gradle文件,查看方式:右上角切換項目結構組織方式,從Android切換為Project


切換后

使用Android Studio新建一個工程后,默認會生成兩個build.gralde文件,一個位于工程根目錄,一個位于app目錄下。一般的三方庫只需要添加到app目錄下即可(即圖中選中的文件),少數三方庫也需要改動工程根目錄下的build.gradle。

  • 下載三方庫的.jar文件,添加到Android工程的libs目錄中,然后刷新build.gradle文件,如上圖所示,gson-02.2.2.jar還有Volley.jar都是這樣安裝的
  • Maven:咳咳,不做介紹...(什么鬼,菜菜的我不知所云 (°ー°〃))
    2.** 使用說明(建議參照Github應用實例,注解詳細哦)**
    (1) 獲取TakePhoto實例
      TakePhoto在作用上類似于FragmentManager,無論是拍照、裁剪、從相冊中選取、壓縮都需要調用TakePhoto的方法,例如:takePhoto.onPickFromGallery();。所以,獲取TakePhoto是第一步,有兩種方式,一般來說,第一種方式更加簡潔,如果通過繼承的方式無法滿足實際項目的使用,可以通過方式二。。

 方式一:通過繼承的方式(參照MainActivity.java)

  • 繼承TakePhotoActivityTakePhotoFragmentActivityTakePhotoFragment
    三者之一。
  • 通過getTakePhoto()獲取TakePhoto實例進行相關操作。
  • 重寫以下方法獲取結果
    void takeSuccess(TResult result);
    void takeFail(TResult result,String msg);
    void takeCancel();

方式二:通過組裝的方式(參照AnotherActivity)
可參照:TakePhotoActivity,以下為主要步驟:

  • 實現TakePhoto.TakeResultListener,InvokeListener接口。
public class AnotherActivity extends AppCompatActivity implements TakePhoto.TakeResultListener,InvokeListener
  • onCreate(),onActivityResult,onSaveInstanceState方法中調用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動態權限所需
        TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
        PermissionManager.handlePermissionsResult(this,type,invokeParam,this);
    }

4.重寫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;
    }

5.添加如下代碼獲取TakePhoto實例:

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

(2) 調用TakePhoto相關方法,并通過以下方法獲取結果

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

舉個栗子:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ···
        takeFromCameraBtn = (Button) findViewById(R.id.take_from_camera);
        takeFromCameraBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                imageUri = getImageCropUri();
                //拍照并裁剪
                takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions);
                //僅僅拍照不裁剪
                //takePhoto.onPickFromCapture(imageUri);
            }
        });
        ···
    }
        ···

    @Override
    public void takeSuccess(TResult result) {
        super.takeSuccess(result);
        String iconPath = result.getImage().getOriginalPath();
        //Toast顯示圖片路徑
        Toast.makeText(this, "imagePath:" + iconPath, Toast.LENGTH_SHORT).show();
        //Google Glide庫 用于加載圖片資源
        Glide.with(this).load(iconPath).into(imageView);
    }

    @Override
    public void takeFail(TResult result, String msg) {
        super.takeFail(result, msg);
        Toast.makeText(MainActivity.this, "Error:" + msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void takeCancel() {
        super.takeCancel();
    }

TakePhoto主要包含以下幾個方法

  • 獲取圖片(調用示例: takephoto.onPickFromDocuments();)
/**
 * 從文件中獲取圖片(不裁剪)
 */
void onPickFromDocuments();
/**
 * 從相冊中獲取圖片(不裁剪)
 */
void onPickFromGallery();
/**
 * 從相機獲取圖片(不裁剪)
 * @param outPutUri 圖片保存的路徑
 */
void onPickFromCapture(Uri outPutUri);
/**
 * 圖片多選
 * @param limit 最多選擇圖片張數的限制
 **/
void onPickMultiple(int limit);
  • 裁剪圖片(調用示例: takephoto.onPickFromCaptureWithCrop(imageUri, cropOptions );)
/**
 * 從相機獲取圖片并裁剪
 * @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 最多選擇圖片張數的限制
 * @param options  裁剪配置
 * */
void onPickMultipleWithCrop(int limit, CropOptions options);
  • 對指定圖片進行裁剪(調用示例: takephoto.onCrop(imageUri, outPutUri, cropOptions);)
/**
 * 裁剪圖片
 * @param imageUri 要裁剪的圖片
 * @param outPutUri 圖片裁剪之后保存的路徑
 * @param options 裁剪配置
 */
void onCrop(Uri imageUri, Uri outPutUri, CropOptions options)throws TException;
/**
 * 裁剪多張圖片
 * @param multipleCrop 要裁切的圖片的路徑以及輸出路徑
 * @param options 裁剪配置
 */
void onCrop(MultipleCrop multipleCrop, CropOptions options)throws TException;
  • 壓縮圖片
 /**
  * 啟用圖片壓縮
  * @param config 壓縮圖片配置
  * @param showCompressDialog 壓縮時是否顯示進度對話框
  * @return
  */
 void onEnableCompress(CompressConfig config,boolean showCompressDialog);
 /**
  * 對指定圖片進行壓縮
  */
new CompressImageImpl(compressConfig,result.getImages(), new CompressImage.CompressListener() {
    @Override
    public void onCompressSuccess(ArrayList<TImage> images) {
        //圖片壓縮成功
    }
    @Override
    public void onCompressFailed(ArrayList<TImage> images, String msg) {
        //圖片壓縮失敗
    }
}).compress();

(3) TakePhoto支持裁剪、壓縮,支持設置裁剪壓縮參數

  • 裁剪
    圖片的裁剪比例setAspectX(1); setAspectY(1)
    是否使用TakePhoto自帶的裁剪工具進行裁剪setWithOwnCrop(false)
  • 壓縮
    圖片最大尺寸setMaxSize(50*1024)
    最大輸出大小setMaxPixel(800)
  • 還是舉個栗子
    private CropOptions cropOptions;  //裁剪參數
    private CompressConfig compressConfig;  //壓縮參數
       ···
//設置裁剪參數
 cropOptions = new CropOptions.Builder().setAspectX(1).setAspectY(1).setWithOwnCrop(false).create();
//設置壓縮參數
 compressConfig=new CompressConfig.Builder().setMaxSize(50*1024).setMaxPixel(800).create();
 takePhoto.onEnableCompress(compressConfig,true);  //設置為需要壓縮
      ...

(4)TakePhoto支持自定義UI,參照Github [README.md](https://github.com/crazycodeboy/TakePhoto)

實現效果截圖




原創文章,轉載請注明出處:http://www.lxweimin.com/p/9528a0d29f29

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容