写在前面
刚开始写安卓的时候,总是希望自己能够亲自实现某个功能,认为只有都是自己写出来的才会学到东西。虽然
有学长跟自己说要多利用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的使用
- 引入三方库依赖(安装)
相信有许多像我一样刚刚上手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)
- 继承
TakePhotoActivity
、TakePhotoFragmentActivity
、TakePhotoFragment
三者之一。- 通过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.jianshu.com/p/9528a0d29f29