Android使用uCrop实现图片裁剪功能

Android使用uCrop实现图片裁剪功能

    • 一、目标
    • 二、下载地址
    • 三、功能设计
    • 四、准备工作
      • 1. 使用com.android.camera.action.CROP调用第三方应用
      • 2. 实现自定义的裁剪功能
    • 五、组合起来
      • 1. 迁移到androidx
      • 2. 不使用native
      • 3. 定制界面
    • 六、Finally

一、目标

Android使用uCrop实现图片裁剪功能_第1张图片

二、下载地址

神马笔记最新版本下载:【神马笔记 版本1.5.0——笔名功能.apk

三、功能设计

笔名中包含2个图片信息——头像和图片签名。

头像比例为1:1,显示为圆形图片。

图片签名比例为2.164:1,显示为长条形矩形图片。

用户可以选择任意的图片,然后通过裁剪图片,转化为目标图片尺寸比例。

四、准备工作

图片裁剪实现方式有2种

  • 调用第三方应用
  • 自己动手写一个

1. 使用com.android.camera.action.CROP调用第三方应用

可以通过设置Intent的Action为com.android.camera.action.CROP来调用第三方应用。

具体的调用方式参考《Android中com.android.camera.action.CROP(图片裁剪)所有属性》。

2. 实现自定义的裁剪功能

虽然是自己动手写一个,当然不是指从零开始实现。我们在GitHub选择一个开源的项目,然后在这基础上进行修改以提高开发效率。

推荐使用uCrop

GitHub项目地址:https://github.com/Yalantis/uCrop

开发者Yalantis的官方介绍:https://yalantis.com/blog/introducing-ucrop-our-own-image-cropping-library-for-android/

五、组合起来

uCrop功能强大并且提供了丰富的配置接口。

通常情况下直接调用uCrop提供的接口即可实现需要的功能。

因为目标设计中要求不显示ActionBar,uCrop并没有提供这样的设置接口,因此采用源代码的形式来使用uCrop。

1. 迁移到androidx

从GitHub clone下来的项目使用的是support包,而主项目工程使用的是androidx包。

要做的第一个便是将uCrop迁移到androidx。

2. 不使用native

从GitHub clone下来的源码,使用的是native的方式。经测试native方式存在2个问题。

  • 增加了安装包体积(0.5M~1.5M,根据打包的so文件而定)
  • 遇到gif裁剪不成功的情况。
    Android使用uCrop实现图片裁剪功能_第2张图片对上图尽心裁剪时,发现裁剪失败,原因未明。

3. 定制界面

  1. 隐藏ActionBar
  2. 增加操作提示——移动和缩放
  3. 增加操作按钮——取消、选取
  4. 使用沉浸式全屏模式

得益于uCrop清晰的代码结构,很容易完成以上功能,实现目标功能。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:id="@+id/ucrop_photobox"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/ucrop_color_toolbar"
            android:minHeight="?attr/actionBarSize"
            android:visibility="gone">

        <TextView
                android:id="@+id/toolbar_title"
                style="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="@string/ucrop_label_edit_photo"
                android:textColor="@color/ucrop_color_toolbar_widget"/>

    androidx.appcompat.widget.Toolbar>

    <FrameLayout
            android:id="@+id/ucrop_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/wrapper_controls"
            android:layout_below="@+id/toolbar"
            android:background="@color/ucrop_color_crop_background">

        <ImageView
                android:id="@+id/image_view_logo"
                android:layout_width="@dimen/ucrop_default_crop_logo_size"
                android:layout_height="@dimen/ucrop_default_crop_logo_size"
                android:layout_gravity="center"
                app:srcCompat="@drawable/ucrop_vector_ic_crop"
                tools:background="@drawable/ucrop_vector_ic_crop"
                tools:ignore="ContentDescription,MissingPrefix"/>

        <com.yalantis.ucrop.view.UCropView
                android:id="@+id/ucrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:alpha="0"/>

        <TextView
                android:textAppearance="@style/TextAppearance.AppCompat.Title.Inverse"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="top|center_horizontal"
                android:layout_marginTop="?actionBarSize"
                android:paddingTop="?listPreferredItemPaddingLeft"
                android:text="@string/ucrop_title"/>


        <TextView
                android:id="@+id/ucrop_btn_cancel"
                android:textAppearance="@style/TextAppearance.AppCompat.Title.Inverse"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|left"
                android:padding="?listPreferredItemPaddingLeft"
                android:layout_marginBottom="?listPreferredItemPaddingRight"
                android:text="@string/ucrop_cancel"
        />


        <TextView
                android:id="@+id/ucrop_btn_choose"
                android:textAppearance="@style/TextAppearance.AppCompat.Title.Inverse"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom|right"
                android:padding="?listPreferredItemPaddingLeft"
                android:layout_marginBottom="?listPreferredItemPaddingRight"
                android:text="@string/ucrop_choose"

        />
    FrameLayout>

RelativeLayout>
void setupImmersive() {
    View view = getWindow().getDecorView();

    {
        int flags = View.SYSTEM_UI_FLAG_VISIBLE;

        flags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        flags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
        flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;

        flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

        //            flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
        flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;

        flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;

        view.setSystemUiVisibility(flags);

    }

    {
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.setStatusBarColor(Color.TRANSPARENT);
    }
}

void setupButtons() {
    findViewById(R.id.ucrop_btn_choose).setOnClickListener(this::onChooseClick);
    findViewById(R.id.ucrop_btn_cancel).setOnClickListener(this::onCancelClick);
}

void onCancelClick(View view) {
    onBackPressed();
}

void onChooseClick(View view) {
    cropAndSaveImage();
}

六、Finally

一些小波折。

导出最终apk文件时,安装包体积从3.6M增加到了5.3M,增加了1.7M。也就是说为了裁剪功能,安装包体积增加了将近一半大小。

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
        ndk {
            abiFilters  "armeabi-v7a"  
        }
    }
}

修改gradle配置文件,打包时只包含armeabi-v7a的so文件以减少安装包大小。修改后的安装包大小为4.0M,增加了0.4M,在可以接受范围内。

之后,在手机上测试时,发现有张gif图片无法裁剪。修改代码不使用native方式,裁剪成功。

因为不需要额外的so文件,安装包大小进一步减小。

~独在异乡为异客~每逢佳节倍思亲~

你可能感兴趣的:(神马笔记)