大家在几乎所有app上都有头像或者证件照裁剪的功能,之所以大家选用uCrop的原因无非是开源成熟(虽然还有一些小bug),但是有些需求就需要UI自定义了(其实在这方面感觉这个库写得稍微有点死了,详细见下),在不修改源码的情况下如何实现
UCropActivity
的样式自定义呢?
比如我们现在这个app就需要在裁剪页面有2个按钮让用户选择裁剪的比例,它看起来是这个样子的:
我们想达到的样子.png它是怎样做到呢?
关于uCrop的设计架构之类的不在本文赘述了,这里只提需要用到的一点:uCrop的裁剪页面(UCropActivity
)其实通过UCrop
这个helper类来跳转到的,在UCrop
源码的是这样的:
public void start(@NonNull Activity activity) {
start(activity, REQUEST_CROP);
}
public void start(@NonNull Activity activity, int requestCode) {
activity.startActivityForResult(getIntent(activity), requestCode);
}
public Intent getIntent(@NonNull Context context) {
mCropIntent.setClass(context, UCropActivity.class);
mCropIntent.putExtras(mCropOptionsBundle);
return mCropIntent;
}
思路:因为最终呈现的样式是uCrop
这个库定死的一个页面(UCropActivity.java
),我们要想在不修改源码的前提下实现修改UI的话最简单的方式就是写一个页面(MyUCropActivity
)继承UCropActivity
,然后在MyUCropActivity
里通过addContentView()
或直接在它的父类(以下所有父类均指UCropActivity
)里找到对应的View
添加对应我们想添加的layout
,然后我们就可以调用父类的方法或属性实现自定义了。
实现:
1、先新建一个MyUCropActivity
继承UCropActivity
;
2、修改跳转到MyUCropActivity
:
//配置基础参数
UCrop uCrop = UCrop.of(uri, Uri.fromFile(new File(getCacheDir(), destinationFileName)));
// uCrop = basisConfig(uCrop);
// uCrop = advancedConfig(uCrop);
//手动设置基础选项
uCrop.withMaxResultSize(1440, 2960);//这是目前最高分辨率的手机了吧(当然,跟图片分辨率没啥关系哈,主要是指呈现出来的分辨率)
//手动设置高级选项
UCrop.Options options = new UCrop.Options();
options.setCompressionFormat(Bitmap.CompressFormat.PNG);
options.setCompressionQuality(100);
options.setHideBottomControls(true);//隐藏底部的按钮些
options.setFreeStyleCropEnabled(false);
options.setShowCropGrid(false);
uCrop = uCrop.withOptions(options);
//uCrop.start(SampleActivity.this);
//跳转到我们的activity,而不是用uCrop自带的跳转到UCropActivity
Intent uCropIntent = uCrop.getIntent(SampleActivity.this);
uCropIntent.setClass(SampleActivity.this,MyUCropActivity.class);
startActivityForResult(uCropIntent,UCrop.REQUEST_CROP);
3、在MyUCropActivity
加入我们的ui
layout_btns.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_32"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:layout_toLeftOf="@+id/btn_23"
android:text="3:2" />
<Button
android:id="@+id/btn_23"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/toolbar"
android:layout_alignParentRight="true"
android:text="2:3" />
</LinearLayout>
MyUCropActivity.java:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View view = LayoutInflater.from(this).inflate(R.layout.layout_btns,null,false);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.BELOW,R.id.toolbar);
lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
RelativeLayout viewGroup = findViewById(R.id.ucrop_photobox);
viewGroup.addView(view,lp);
view.findViewById(R.id.btn_32).setOnClickListener(this);
view.findViewById(R.id.btn_23).setOnClickListener(this);
}
4、设置事件。这里要提到一点就是上面说的自定义不是很科学的地方,UCropActivity
里的绝大部分方法全是私有的!
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_23:
setRatio(2/3f);
break;
case R.id.btn_32:
setRatio(3/2f);
break;
}
}
/**
* 反射设置比例
*/
public void setRatio(float ratio) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("mGestureCropImageView");
field.setAccessible(true);
GestureCropImageView gestureCropImageView = (GestureCropImageView) field.get(this);
gestureCropImageView.setTargetAspectRatio(ratio);
gestureCropImageView.setImageToWrapCropBounds();
} catch (Exception e) {
e.printStackTrace();
}
}
好了,结束,希望能帮助到有需求的小伙伴。
PS:由于在uCrop的github上面的混淆规则里已经包含了,所以我们这里无需额外对这个反射设置什么混淆规则。
网友评论