uCrop的UI自定义?

大家在几乎所有app上都有头像或者证件照裁剪的功能,之所以大家选用uCrop的原因无非是开源成熟(虽然还有一些小bug),但是有些需求就需要UI自定义了(其实在这方面感觉这个库写得稍微有点死了,详细见下),在不修改源码的情况下如何实现UCropActivity的样式自定义呢?

比如我们现在这个app就需要在裁剪页面有2个按钮让用户选择裁剪的比例,它看起来是这个样子的:
2602023-fd3a542da831f3bf.png
我们想达到的样子.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上面的混淆规则里已经包含了,所以我们这里无需额外对这个反射设置什么混淆规则。

猜你喜欢

转载自blog.csdn.net/weixin_34199405/article/details/86819469