本人能力不足,在看到源码最后一部分的时候大量抄袭可能是最详细的UCrop源码解析
文章目录
1. uCrop简介
uCrop是目前较火的图片裁剪框架,开发者宣称他会比目前市面上所有的图片裁剪方案都要更流畅。外加他封装程度较高,可自定义,而且颜值很高(似乎这个才是重点),现在越来越多APP选择使用它。
github
2. 使用方法
得益于uCrop优秀的封装,uCrop的使用方法特简单。
2.1 导入依赖
-
先在项目的
build.gradle
中添加allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } }
并在
module
的build.gradle
中添加implementation 'com.github.yalantis:ucrop:2.2.3'
- 轻量级框架implementation 'com.github.yalantis:ucrop:2.2.3-native'
- 获得框架全部强大的功能以及图片的高质量(最终可能会导致apk的大小增加1.5MB以上) -
由于框架的本质是调用到另一个Activity去处理图片,所以需要在AndroidManifest.xml中将UCropActivity添加进去
<activity android:name="com.yalantis.ucrop.UCropActivity" android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
到这你就能把cUrop全部导入到你的项目里面了,接下来咱们就拉将如何调用
2.2 开始基本的调用
调用起来很简单:
UCrop.of(sourceUri, destinationUri)
.start(context);
其中sourceUri
是输入图片的Uri
,destinationUri
是输出图片的Uri
。然后他就会由Intent
的调动跳到UCropActivity
,用户就在UCropActivity
里面进行图片裁剪操作,然后最后由UCropActivity
发起一个Intent
回到你的Activity
。
2.3 处理回来的数据
由于是从UCropAcitivity
传回数据,所以你需要在你的Activity
里面的onActivityResult
方法处理uCrop
返回的信息:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
final Uri resultUri = UCrop.getOutput(data);
} else if (resultCode == UCrop.RESULT_ERROR) {
final Throwable cropError = UCrop.getError(data);
}
}
到这,基本用法就完了,你就可以尽情的使用uCrop。但是我前面说过,uCrop封装程度好,这点很多图片处理框架都可以做到,基本上都是把需要的数据传到自己的Activity之后由自己的Activity处理,所以很多框架看起来都有优秀的封装,那uCrop相比其他又有啥好呢,答案就是自定义灵活:
2.4 uCrop高阶用法
2.4.1 配置uCrop
/**
* 启动裁剪
* @param activity 上下文
* @param sourceFilePath 需要裁剪图片的绝对路径
* @param requestCode 比如:UCrop.REQUEST_CROP
* @param aspectRatioX 裁剪图片宽高比
* @param aspectRatioY 裁剪图片宽高比
* @return
*/
public static String startUCrop(Activity activity, String sourceFilePath,
int requestCode, float aspectRatioX, float aspectRatioY) {
Uri sourceUri = Uri.fromFile(new File(sourceFilePath));
File outDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!outDir.exists()) {
outDir.mkdirs();
}
File outFile = new File(outDir, System.currentTimeMillis() + ".jpg");
//裁剪后图片的绝对路径
String cameraScalePath = outFile.getAbsolutePath();
Uri destinationUri = Uri.fromFile(outFile);
//初始化,第一个参数:需要裁剪的图片;第二个参数:裁剪后图片
UCrop uCrop = UCrop.of(sourceUri, destinationUri);
//初始化UCrop配置
UCrop.Options options = new UCrop.Options();
//设置裁剪图片可操作的手势
options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL);
//是否隐藏底部容器,默认显示
options.setHideBottomControls(true);
//设置toolbar颜色
options.setToolbarColor(ActivityCompat.getColor(activity, R.color.colorPrimary));
//设置状态栏颜色
options.setStatusBarColor(ActivityCompat.getColor(activity, R.color.colorPrimary));
//是否能调整裁剪框
options.setFreeStyleCropEnabled(true);
//UCrop配置
uCrop.withOptions(options);
//设置裁剪图片的宽高比,比如16:9
uCrop.withAspectRatio(aspectRatioX, aspectRatioY);
//uCrop.useSourceImageAspectRatio();
//跳转裁剪页面
uCrop.start(activity, requestCode);
return cameraScalePath;
}
2.4.2 其他配置
//设置Toolbar标题
void setToolbarTitle(@Nullable String text)
//设置裁剪的图片格式
void setCompressionFormat(@NonNull Bitmap.CompressFormat format)
//设置裁剪的图片质量,取值0-100
void setCompressionQuality(@IntRange(from = 0) int compressQuality)
//设置最多缩放的比例尺
void setMaxScaleMultiplier(@FloatRange(from = 1.0, fromInclusive = false) float maxScaleMultiplier)
//动画时间
void setImageToCropBoundsAnimDuration(@IntRange(from = 100) int durationMillis)
//设置图片压缩最大值
void setMaxBitmapSize(@IntRange(from = 100) int maxBitmapSize)
//是否显示椭圆裁剪框阴影
void setOvalDimmedLayer(boolean isOval)
//设置椭圆裁剪框阴影颜色
void setDimmedLayerColor(@ColorInt int color)
//是否显示裁剪框
void setShowCropFrame(boolean show)
//设置裁剪框边的宽度
void setCropFrameStrokeWidth(@IntRange(from = 0) int width)
//是否显示裁剪框网格
void setShowCropGrid(boolean show)
//设置裁剪框网格颜色
void setCropGridColor(@ColorInt int color)
//设置裁剪框网格宽
void setCropGridStrokeWidth(@IntRange(from = 0) int width)
3. 源码解析
在我开始说源码之前,我建议大家可以先看下我下面的连接,因为本框架的作者真的是个好人,他不仅为我们贡献了这么好的一个框架,还把自己写这个框架的思路都写了出来,大家可以看看
英文原版
国内网友翻译版
百度网页翻译机翻版
其实我个人感觉百度机翻没有谷歌翻译的好,大家有条件的可以使用谷歌翻译浏览器插件翻译整个网页(谷歌翻译好像国内可以直接访问)
代码结构大致分为三个部分:
3.1 第一部分:UCropActivity(整个框架的外在,用户操作图片的地方)
他的功能就是项目主要的界面,以及实现一些基本的初始化。你跳转到uCrop看到的那个操作图片的界面就是它。
这块看源码的时候代码居多,但是,说实话,就像刚刚说的一样,他除了初始化还是初始化。初始化完Toolbar
接着初始化ViewGroup
,初始化完ViewGroup
接着初始化Image
数据等等。所以这块我就没咋细看~~(其实是因为代码太长了,逃)~~
3.2 第二部分:OverlayView(绘制裁剪框)
这一块主要就是来画你所看到的图片中的裁剪的辅助线。
在构造方法里面就调用了一个方法,就是init()
,而init()
方法也就干了一件事——判断。当系统小于JELLY_BEA_MR2
也就是Android4.3
时,启动了硬件加速,至于为什么setLayerType(LAYER_TYPE_SOFTWARE, null);
这个看着就像启动硬件加速的方法,甚至参数里面还有软件这个单词的方法能启动硬件加速,请大家移步HenCoder Android 自定义 View 1-8 硬件加速(进去直接搜索这个方法即可,就能找到解释的地方),我再次不做解释。
这个类主要有两个方法
drawDimmedLayer()
绘制裁剪框之外的灰色部分drawCropGrid()
绘制裁剪框
那我们分别来看下这两个方法:
3.2.1 drawDimmedLayer()
protected void drawDimmedLayer(@NonNull Canvas canvas) {