Android拍照相册裁剪封装

本文介绍了如何封装一个Android拍照和相册选择并裁剪图片的功能,包括解决6.0以上权限问题、7.0以上Uri问题、重复选择图片的处理,以及提供了详细代码和注意事项。通过封装的类,开发者只需几行代码即可快速集成图片选择和裁剪功能。
摘要由CSDN通过智能技术生成


最近用到从相机/相册选择图片的功能,这个功能虽然不复杂,网上的代码也一大堆,但是考虑到可能以后别的地方也会用到,所以就抽个空封装了一个类,来实现此功能。

先列出来需要解决问题

  • 这个类需要具备哪些功能

至少要支持:相机、相册、裁剪、裁剪比例设定、缩放功能,因为使用系统的自带的裁剪功能,所以如裁剪成圆形、裁剪时展示网格、图片进行二次压缩等功能暂且不论。

  • 如何能够在下次使用的时候快速集成进去

如果要快速集成,最好是几行代码就可以得到选择之后的图片,那么就需要将弹出相机/相册选择框、拍照/选择相册之后的裁剪逻辑、图片保存逻辑、权限检查逻辑、7.0以上Uri逻辑、版本兼容问题都在一个类中完成,使用者只需要设置开关参数即可。

  • 6.0以上权限问题

6.0以上动态检查权限问题、设置了targetSdkVersion设置为23以下时正常的权限检查无效问题,没有权限时自动获取权限。

  • 7.0以上Uri问题

在7.0版本以上系统设定不能直接使用本地真是路径的Uri,必须使用FileProvider封装之后才可以获取,但是这个也是分情况的,具体下面会提到。

  • 重复选择拍照时产生的垃圾文件问题

选定一张图片后,觉得不好重新由选择了一张,之前的那个图片文件怎么处理,如果加入裁剪功能,那么裁剪后拍照的原图怎么处理。如果像发朋友圈一样需要连续多张图片时,产生的文件会不会冲突?

展示效果

先上效果图,然后说代码:

image.png

注意事项

根据前面提到的几个问题,有以下几点需要说明:

  • 封装一个类,传入Activity上下文(没有使用content是因为需要打开相机、相册等intent需要startactiity,虽然fragment也可以,但是这样在纯activity中就无法使用了),提供是否裁剪、裁剪比例、裁剪输出尺寸、是否缩放的开关方法,并提供默认值,可以在使用过程中自行改动。使用PopupWindow展示选择框(当然也可以使用dialog),这样可以自由控制选择框的。

  • 弹出选择框时检查权限,如果没有权限则进行权限申请,如果用户点击了已拒绝授权,弹出设置界面,引导用户授权,授权成功后弹出选择框。

  • 提供回调接口,在获取图片成功之后通过回调返回图片的路径。

  • 相机拍照、相册选择之后、裁剪之后、权限回调需要通过onActivityResultonRequestPermissionsResult来实现,所以使用的地方需要将这两个方法传递给封装的类。

  • 前面提到过的7.0以上Uri问题,使用FileProvider来实现。但是如果项目的targetSdkVersion设置成23以下的话,即使在7.0以上手机上,也可以不用FileProvider的形式来获取Uri,不过targetSdkVersion在23以下,在小米市场无法上传安装包(目前我就知道这个市场)

  • 在4.4开始,从相册选择照片返回的Uri就不能直接使用,所以需要经过转化才能得到真实的图片路径。

  • 7.0以上,targetSdkVersion设置为23以上时,相机拍照输出的uri需要通过FileProvider获取的,否则会抛出异常。裁剪输入的uri为普通形式获取的uri,裁剪输出的uri需要时通过FileProvider转换的uri,要不会提示无法载入图片/无法保存裁剪的图片。

  • 图片裁剪时,可以选择直接return-datatrue或者false,true则直接返回对应的bitmap,false需要制定一个输出uri,为了内存考虑,在封装时,选择false,让其返回对应的uri(需要考虑targetSdkVersion和7.0以上的uri问题)

  • targetSdkVersion设置为23以下时,从相机拍照时会生成一个图片,可以得到一个对应的uri,如果需要裁剪,可以继续使用该uri,系统会自动替代之前的拍照生成的文件,这样减少了无用文件。但是设置targetSdkVersion大于23,且在高版本(这个没有具体研究是哪一个版本,我测试的是华为8.1)使用同一个uri裁剪时,会抛出一个已存在的错误。所以封装类中相机拍照后裁剪输入和输出的uri处理成不同的,裁剪完成后再删除拍照时生成的图片。

  • 文件的命名使用当前时间戳,保存在sd卡下面以项目包名为名的文件夹下。

  • 为了方便代码集成,一些处理图片、处理uri的公共方法,也封装到一个类中,如果觉得不合适可以自行单独出来一个工具类(或者自己的项目中已经有对应的方法就可以删掉对应的代码)。

  • 在fragment中使用时,因为传递的是activity,所以onActivityResult等方法是fragment对应的activity先接收到,需要activity传递给fragment在传递到这个类中

  • 代码中有详细的注释

  • 以上代码在三星GT-I9300(Android 4.3),华为Mate10Pro(Android8.1)中测试过。

代码

  • 主要的类(SelectPictureManager.java)
import android.Manifest;
import android.app.Activity;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v4.content.PermissionChecker;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
​
/**
 * 管理选择相册的类
 * Application
 * Created by anonyper on 2018/11/19.
 */
​
public class SelectPictureManager {
 /*
 定义返回的code值
 */
 public static final int TAKE_PHOTO_CODE = 1000;//拍照
 public static final int CHOOSE_PHOTO_CODE = 2000;//选择相册
 public static final int PICTURE_CROP_CODE = 3000;//剪切图片
 public static final int REQUEST_PERMISSIONS = 4000;//授权code
​
 private boolean isNeedCrop = false;//是否需要裁剪 默认不需要
 private boolean isScale = true;//是否需要支持缩放 在可裁剪情况下有效
 private boolean isContinuous = false;//是否是连拍模式 比如连续需要两张以上照片
 private String fileName;//文件名字
 private String oldFileName;//拍照裁剪时的原图片 需要删掉
 private Uri outImageUri;//相机拍照图片保存地址
 private int aspectX = 1000;//裁剪的宽高比例
 private int aspectY = 1001;//裁剪的宽高比例 两个比例略微不一样是为了解决部分手机1:1时显示的时圆形裁剪框
 private int outputX = 400;//裁剪后输出图片的尺寸大小
 private int outputY = 400;//裁剪后输出图片的尺寸大小
​
 Activity activity;//全局上下文 需要
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值