这篇文章主要介绍了 Android 高仿 QQ 图片选择器的实现思路,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起看看吧
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
当做一款 APP,需要选择本地图片时,首先考虑的无疑是系统相册,但是 Android 手机五花八门,再者手机像素的提升,大图无法返回等异常因数,导致适配机型比较困难,微信、QQ 都相继的在自己的 APP 里集成了图片选择功能,放弃了系统提供的图片选择器,这里仿造 QQ 做了一个本地图片选择器,PS:之前有人说 "仿" 写成 "防" 了,今儿特意注意了下,求不错。
先上一张效果图,无图无真相啊~~~
实现的效果大概是这样的:
1. 单选:跳转到本地图片选择文件夹,选择文件夹后,进入到该文件夹下的所有图片,选择某张图片后,返回改图片地址信息
2. 多选:跳转到图片文件夹,选择一个文件夹,选择图片,点击右上角的小圆圈,选中该图,点击图片其他区域,查看大图,点击预览,查看已选图片,可以跨文件夹选择图片。
为了达到这效果,需要做几件事:
1. 读取本地所有 有图片的文件夹:
这里用 ContentResolver 读取媒体文件
- String[] columns = {
- MediaStore.Images.Media._ID,
- MediaStore.Images.Thumbnails.DATA,
- MediaStore.Images.Media.DATA,
- MediaStore.Images.Media.BUCKET_ID,
- MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
- "COUNT(1) AS count"
- };
- String selection = "0==0) GROUP BY (" + MediaStore.Images.Media.BUCKET_ID;
- String sortOrder = MediaStore.Images.Media.DATE_MODIFIED;
- Cursor cursor = contentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selection, null, sortOrder);
这是一个简单的 SQL 查询语句,按文件夹分组,并返回文件夹下图片数。
2. 读取指定文件夹下所有图片:
当选择某一目录时,需要读取该目录下所有图片了。
- String[] columns = new String[] {
- MediaStore.Images.Media._ID,
- MediaStore.Images.Media.DATA
- };
- /*查询文件路径包含上面指定的文件夹路径的图片--这样才能保证查询到的文件属于当前文件夹下*/
- String whereclause = MediaStore.Images.ImageColumns.DATA + " like'" + folderPath + "/%'";
- Log.i("queryGalleryPicture", "galleryPath:" + folderPath);
- Cursor corsor = c.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, whereclause, null, null);
这里的查询语句是根据文件名字来过滤的,只要图片路径包含文件夹路径的,则为该文件夹下的图片
3.UI 交互
首先在展示所有包含图片的文件夹时,异步加载有图片的文件夹,读取成功后列表展示,这里用的 RecyclerView 展示列表信息,点击某一目录时,在读取改目录下的图片,在图片展示页里,需要注意的是,每次点击判断当前点击图片是否已在选择列表中,若在,删除,不在,添加。这里图片加载用了开源框架 ImageLoader
- if (mSelectlist.contains(imageBean)) { //点击的item为已选过的图片时,删除
- mSelectlist.remove(imageBean);
- subSelectPosition();
- } else { //不在选择列表里,添加
- if (mSelectlist.size() >= maxCount) {
- Toast.makeText(mContext, mContext.getResources().getString(R.string.publish_select_photo_max, maxCount), Toast.LENGTH_SHORT).show();
- return;
- }
- mSelectlist.add(imageBean);
- imageBean.selectPosition = mSelectlist.size();
- }
- //通知点击项发生了改变
- notifyItemChanged(position);
同时没删除一张图片,图片上的序号相应的作改变,然后通知改变项更新 UI。
不同 Activity 跳转时,因为要传递图片列表 List,list 里是自定义实体类,刚开始考虑过用 intent 传递,但是 intent 传递后,通过 list.get(positon).contains 比较是否同一对象时,始终是不同对象,大家可以去验证下。所以这里定义了一个观察者的类,去保存选择的图片和文件夹下的所有图片,同时查看大图时,若选择了一张或者取消选择了一张图,通过观察者通知更新即可
- /**
- * 通知图片选择已改变
- */
- public void updateImageSelectChanged () {
- setChanged();
- notifyObservers(imgSelectObj);
- }
好了,有了以上的,就可以使用我们的图片选择器了:
单选时,在需要的地方调用:
- /*单选,参数对应的是context, 回调*/
- FolderListActivity.startSelectSingleImgActivity(this, 2);
- 多选时:
- /*参数对应context, 回调code, 传入的图片List, 可选的最大张数*/
- FolderListActivity.startFolderListActivity(this, 1, null, 9);
最后 Activity 的 onActivityResult 中接收返回的图片数据:
- List<ImageFolderBean> list = (List<ImageFolderBean>) data.getSerializableExtra("list");
源码下载地址:
来源: http://www.phperz.com/article/17/0316/295220.html