Android-如何开发一个功能强大的图片选择器
图片选择器是Android开发中会经常用到的一个功能,特别对于社交类的应用,比如头像设置,比如发图片。自然ImagePicker的轮子很多,今天介绍一个功能强大的轮子SImagePicker
https://github.com/martin90s/ImagePicker
介绍
首先功能强大之处
- 首先基本的图片读取显示,以及图片更新监控
- 超大图片预览,比如一张19M,10000*5000px的图片
- 图片的裁剪功能
- 丰富的可配置项,支持拍照选取,选取张数定义,支持选择的图片过滤,
支持多种图片加载器(Fresco,Glide等)
第一张头像模式,第二张选择多张图片(包括动画和顺畅的跳转),第三张是分片加载超大图(19.5M,10000*5000px)
头像模式,支持裁剪 多选图片,流畅的页面跳转 超大图预览,可以看到渐变加载 如何使用 1.首先初始化(推荐在Application的oncreate中调用)
SImagePicker.init(new PickerConfig.Builder().setAppContext(this)
.setImageLoader(new FrescoImageLoader())
.setToolbaseColor(getColor(R.color.colorPrimary))
.build());
2.在需要选择图片的地方调用
SImagePicker
.from(MainActivity.this)
.maxCount(9)
.rowCount(3)
.pickMode(SImagePicker.MODE_IMAGE)
.fileInterceptor(new SingleFileLimitInterceptor())
.forResult(REQUEST_CODE_IMAGE);
可配置项
1.全局配置(即初始化时传入的PickerConfig,此配置作用于SImagePicker整个使用过程)
配置参数 | 参数含义 |
---|---|
setImageLoader(ImageLoader) | 使用的图片加载器。demo工程中实现了Fresco和Glide两种ImageLoader,可以参考 |
setToolbarColor(int) | Picker的主色调,默认值是App的primaryColor |
setAppContext(Context) | Picker内部用到的Context,传入ApplicationContext即可 |
配置参数 | 参数含义 |
---|---|
from(Activity or Fragment) | 调用图片选择器可从Activity或者Fragment进入,最后的结果会在onActivityResult()返回,现在返回的结果有两个值,用户选择的图片的路径列表data.getStringArrayListExtra(PhotoPickerActivity.EXTRA_RESULT_SELECTION); 用户是否选择了原图data.getBooleanExtra(PhotoPickerActivity.EXTRA_RESULT_ORIGINAL, false); |
maxCount(int) | 此次选择允许的最大选择数量,默认是1.比如发朋友圈最多选择9张图就传9 |
rowCount(int) | 图片列表单排展示多少张图 |
setSelected(List) | 默认已经被选中的图片 |
pickMode(int) | 选图的模式,现在有头像模式和普通模式两种,头像模式选中图片后默认会跳到图片裁剪页面且默认只能选择一张 |
cropFilePath(String) | 头像模式下裁剪图片存放地址 |
showCamera(boolen) | 是否要展示拍照入口 |
pickText(int) | Picker里右下角展示的文字信息(比如配置选择,发送,完成) |
fileInterceptor(FileChooseInterceptor) | 图片过滤器,比如用户选择的单张图片大小有限制,即可写在这个拦截器中,当用户选择过大图片时可以提示并且过滤 |
forResult(int requestCode) | 打开图片选择器,并且传入requestCode |
在调用图片选择器的Fragment或者Activity中
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE) {
final ArrayList pathList =
data.getStringArrayListExtra(PhotoPickerActivity.EXTRA_RESULT_SELECTION);
final boolean original =
data.getBooleanExtra(PhotoPickerActivity.EXTRA_RESULT_ORIGINAL, false);
}
}
实现 图片数据库读取CursorLoader 【Android-如何开发一个功能强大的图片选择器】Android3.0中引入了加载器/装载器(Loader)的功能,主要用于异步的方式加载数据库。装载器Loader的特点:
- 装载器提供异步数据加载的能力
- 装载器监视数据资源并且当内容改变时发送新的结果;
- 在配置改变后重建的时候,装载器自动的重连最后的装载器游标,因此,不需要重新查询数据。
源码中的对应
WechatIMG90.jpeg PhotoLoader初始化
public static CursorLoader newInstance(Context context, Album album, long minSize) {
if (album == null || album.isAll()) {
return new PhotoLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION,
SELECTION_SIZE, new String[] {minSize + ""}, ORDER_BY);
}
return new PhotoLoader(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, PROJECTION,
MediaStore.Images.Media.BUCKET_ID + " = ? and (" + SELECTION_SIZE + ")", new String[] {
album.getId(), minSize + ""}, ORDER_BY);
}
超大图片加载 对于超大的图片如何展示,这个是个比较棘手的问题
比如这张图http://7xpb9x.com1.z0.glb.clouddn.com/2017/01/20/b578e4755a32ac56a9c4b9a1f7e2822d.jpg
10000*5000的像素,接近20M。
这种图片肯定无法一次全部load到内存中,可以稍微计算一下即使是RGB_565的方式全部load进内存也要占用几乎90M的内存,显然是不太可能。可以回头看一下第三张demo gif,显然用户打开一张图时,在默认情况下,并不要求能看到细节,当用户点击某区域放大时此时才会需要这一块的清晰图。那么如何展示这种超大图的思路基本基本就是
- 首先拿到文件路径,读取出图片的宽高,并且根据屏幕和图片宽高计算出一个展示全图的情况下的Samplesize,根据这个值去加载出一个全景的图
- 对图片进行分块,分块会分出不同放大倍数下(即选择不同SampleSize)下的一个块列表,比如放大2倍时,放大4倍时对应怎么分块
- 当用户点击放大某一区域时,根据放大的倍数以及当前的中心点选择对应的块进行load和渲染
并且根据picker的需求做了些修改,来实现超大图的预览
图片列表展示 展示 由于使用了cursorLoader,对于ListView的话有CursorAdapter可以使用,但是对于RecyclerView确没有对应的Adapter,所以在源码中可以看到实现了一个RecycleCursorAdapter,用于实现从cursor获取数据已经自动刷新。
兼容 为了能够兼容多个图片加载器,SImagePicker抽象了一个ImageLoader接口用于让使用者自定义对应的图片加载器。
使用建议 SImagePicker提供了jitpack上的依赖库,可以很快的接入业务中,但是由于大部分的APP对于ImagePicker的使用都有各种业务需求,且SImagePicker只是抽象出了比较通用的一些配置,用于让使用者能快速集成,所以此处还是建议使用者尽可能源码引用的方式的使用SImagePicker,既方便做一些调试,也可以很快的了解实现原理,说起来这种UI组件代码应该是很好读的,因为本身并不复杂。
写一篇技术文真心累,这个B实在是装不下去了
再次附上github链接:
- https://github.com/martin90s/ImagePicker
推荐阅读
- 如何有效的实现“辅助阅读”|如何有效的实现“辅助阅读”|《如何阅读一本书》Day12
- 前端开发|值得推荐的Vue 移动端UI框架
- 如何向Spring IOC 容器 动态注册bean
- 如何在招聘面试中提高效率()
- 《微信小程序》开发 问题记录
- 如何用Python实现配置热加载()
- Android-基础|Android基础教程之-----布局
- 电子商务系统怎么开发,有哪些流程_OctShop
- 投稿|从假AI到真AI,虚拟人是如何进化的?
- GD32开发|GD32F4xx串口收发,DMA+空闲中断