GitHub地址
知乎APP开源的一个图片选择器,并内置了两套主题,UI设计基本满足大部分APP需求。
接入:
非常简单,只需要在gradle中配置:
repositories {
jcenter()
}
dependencies {
compile 'com.zhihu.android:matisse:0.4.3'
}
你还需要在Manifest添加2个权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
在6.0以上的版本时,需要使用动态权限:Android 6.0 运行时权限处理完全解析
使用:
使用上也比较方便,官方给出的示例:
// 配置和启用
Matisse.from(MainActivity.this)
.choose(MimeType.allOf())
.countable(true)
.maxSelectable(9)
.addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
.gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
.thumbnailScale(0.85f)
.imageEngine(new GlideEngine())
.forResult(REQUEST_CODE_CHOOSE);
// 在Activity或Fragment中接收结果
List<Uri> mSelected;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CHOOSE && resultCode == RESULT_OK) {
mSelected = Matisse.obtainResult(data);
Log.d("Matisse", "mSelected: " + mSelected);
}
}
我们慢慢的分析
/*
* Start Matisse from an Activity.
* 需要传入一个Activity作为参数,返回一个Matisse实例,一切的基础
*/
Matisse.from(MainActivity.this)
/*
* 选择图片可选类型,并返回一个SelectionSpecBuilder对象,通过这个对象进行进一步的配置
* 参数要求为Set<MimeType>,MimeType是一个枚举,包括 JPEG,PNG,GIF 3个类型
* 作用要注意,这里不是设置显示图片的类型,而是设置可选的图片类型
* 简单来说,例如这里配置GIF,图片选择器仍然会显示所有类型的图片,但是只有GIF格式的图片是可选的
* 可以使用MimeType.allOf()允许选择所有格式,也可以使用MimeType.of(MimeType...)限制选择部分格式
*/
.choose(MimeType.allOf())
/*
* 当选择图片的时候,图片的右上角是显示普通的“√”,还是显示具体的数字,true则为显示具体数字
* 显示数字的话,会根据你选择的顺序,将右上角的标识显示为 1,2,3,4...
*/
.countable(true)
/*
* 图片选择的最大数量,默认为1(这个1大有深意,我也不知道为什么)
*/
.maxSelectable(9)
/*
* 添加过滤器
* GifSizeFilter是simple里面的一个过滤器示例,
* 注意这个过滤器的作用,不是用来过滤图片类型的,
* 而是在选择图片的时候,当图片满足一定情况下,弹出一个提示框,并禁止选择该图片。
* 如示例的GifSizeFilter,作用是在支持选择GIF的前提下,对宽度或高度不足320,或体积大于5m的GIF图片作出拦截,
* 当选择符合该特征的图片时,Filter会返回一个带有错误信息的UncapableCause类,其中的信息将会在一个弹出框中显示
* 总结就是:禁止选择某些指定条件的图片,并告诉用户为什么不能选
*/
.addFilter(new GifSizeFilter(320, 320, 5 * Filter.K * Filter.K))
/*
* 设置Grid布局中图片的宽度,但是由于显示的图片布局性质,设置的值不一定会准确执行,但是会接近给出的值
* 例如屏幕是1000的话,设置300,图片有2种可能
* 图片宽度250,一行4张图片 / 图片宽度330,一行3张图片
* 由于宽度330比较接近给出的数值300,图片布局将会使用一行3个的布局
* 如果以上情况套用到了1200的屏幕宽度的话,自然就会显示为一行4个的布局
*/
.gridExpectedSize(getResources().getDimensionPixelSize(R.dimen.grid_expected_size))
/*
* 这个图片选择器Activity的显示方向,默认为竖屏 SCREEN_ORIENTATION_PORTRAIT
* 通常的参数
* SCREEN_ORIENTATION_UNSPECIFIED : 由Android系统自己选择合适的方向
* SCREEN_ORIENTATION_PORTRAIT : 竖屏
* SCREEN_ORIENTATION_LANDSCAPE : 横屏 (由于默认一行3个的布局,不设置gridExpectedSize的话,图片将会无比巨大)
*/
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
/*
* 缩略图的压缩值,要求(0.0, 1.0]区间的float参数,默认0.5,既压缩一半
* 注意框架不会帮你自动修正,设置错误直接就会抛出一个IllegalArgumentException
*/
.thumbnailScale(0.85f)
/**
* 关键的一点,设置图片加载引擎,不设置不闪退算我输
* 参数是一个实现ImageEngine接口的类,官方提供了两个已经实现好的引擎参数:
* GlideEngine :使用Glide实现的ImageEngine,内部使用了Glide作为加载框架
* PicassoEngine :使用Picasso实现的ImageEngine
* 如果你使用其他框架,或者不使用框架,你需要自行实现一个ImageEngine
* 总之就是要设置一个imageEngine
*/
.imageEngine(new GlideEngine())
/*
* 配置完成后,调用这个方法就可以进入图片选择框架了
* 这里的REQUEST_CODE_CHOOSE其实是自定义的RequestCode,在方法内部调用的startActivityForResult使用该参数
* 通过startActivityForResult跳转到MatisseActivity
* 配置的参数被保存到了SelectionSpec的InstanceHolder中
*/
.forResult(REQUEST_CODE_CHOOSE);
由于使用了startActivityForResult启动Activity的方式,接收回调就需要使用onActivityResult()
List<Uri> mSelected;
...
/*
* 返回的数据使用了ArrayList<Uri>封装,通过putParcelableArrayListExtra添加到intent,
* 键为 String EXTRA_RESULT_SELECTION = "extra_result_selection";
* 或者直接使用Matisse.obtainResult去解析返回的intent,取出List<Uri>的返回值
*/
mSelected = Matisse.obtainResult(data);
以上就是官方示例的详细解析。
配置SelectionSpecBuilder余下的其他方法:
/*
* 设置Style,官方给出两个主题
* R.style.Matisse_Zhihu :知乎的蓝色主题
* R.style.Matisse_Dracula :上面图片中部黑色一坨(黑中带蓝)的主题
* 你也可以根据这两个主题去自定义自己的主题
*/
public SelectionSpecBuilder theme(@StyleRes int themeId)
/*
* 一个优秀的图片选择框架必然能拍照,这里就是拍照开关了
* 然后你还需要调用captureStrategy()设置照片信息,不设置不闪退算我又输
*/
public SelectionSpecBuilder capture(boolean enable)
/*
* 传入一个CaptureStrategy对象设置拍照的照片信息
* 这个CaptureStrategy的构造方法要求传入两个值
* boolean isPublic:是否公开,true的话会把图片存放到ExternalStoragePublicDirectory的PICTURES目录下,
否则将会放在ExternalFilesDir的PICTURES目录下
* String authority:用于配置FileProvider(注1),与provider配置中的android:authorities属性保持一致
*/
public SelectionSpecBuilder captureStrategy(CaptureStrategy captureStrategy)
/*
* 设置一行图片的数量,设置成5,一行就会显示5张图片,适用于横竖屏
* 如果设置了gridExpectedSize的话,将会优先使用gridExpectedSize计算出的数量
* 如果你需要适配横竖屏,可以优先选择设置gridExpectedSize
*/
public SelectionSpecBuilder spanCount(int spanCount)
注1:关于FileProvider,可以参考FileProvider共享文件、缓存,
以及可能出现的FileProvider相关 Failed to find configured root that contains
混淆:
官方文档上的混淆规则,其实就是当你使用了图片框架时,图片框架自己的混淆规则
如使用了GlideEngine,就使用了Glide的混淆规则:
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
# for DexGuard only
-keepresourcexmlelements manifest/application/meta-data@value=GlideModule
使用使用PicassoEngine,则是Picasso的混淆规则:
-dontwarn com.squareup.okhttp.**
所以,其实可以根据具体的使用情况,进行配置混淆。
相当于不用写,手动滑稽
如对你有帮助,欢迎点赞喜欢支持
网友评论