uCrop的UI自定义?

作者: v587的毅哥 | 来源:发表于2019-01-13 11:17 被阅读11次

    大家在几乎所有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上面的混淆规则里已经包含了,所以我们这里无需额外对这个反射设置什么混淆规则。

    相关文章

      网友评论

        本文标题:uCrop的UI自定义?

        本文链接:https://www.haomeiwen.com/subject/ueekdqtx.html