相册(1) ---- 获取所有照片并按照时间分组
文章目录
效果图
一. 使用的第三方依赖及知识点
1. recyclerView适配器BaseRecyclerViewAdapterHelper
https://github.com/CymChad/BaseRecyclerViewAdapterHelper/releases
使用
- (1) 继承
BaseMultiItemQuickAdapter
因为集合中有两个种集合对象, 而这两种集合对象都实现了MultiItemEntity
接口, 所以此处实体写为MultiItemEntity
- (2) 在构造方法中添加两种布局的
//TYPE_HEADER和TYPE_DATA为定义的两个常量 //实现MultiItemEntity接口的实体类需要实现getItemType()方法,返回值即为TYPE_HEADER或TYPE_DATA addItemType(TYPE_HEADER, R.layout.tab1_item_header) addItemType(TYPE_DATA, R.layout.tab1_item_photo)
- (3) 实体类实现
MultiItemEntity
接口,getItemType()
方法返回两种TYPE
2. 粘性头部 PinnedSectionItemDecoration
https://github.com/oubowu/PinnedSectionItemDecoration
使用
- (1) 在adapter中添加如下代码
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, TYPE_HEADER)
}
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
super.onViewAttachedToWindow(holder)
FullSpanUtil.onViewAttachedToWindow(holder, this, TYPE_HEADER)
}
注: 此处提供一个通用的BaseHeaderAdapter
abstract class BaseHeaderAdapter<T : MultiItemEntity>(data: List<T>) :
BaseMultiItemQuickAdapter<T, BaseViewHolder>(data) {
init {
addItemTypes()
}
protected abstract fun addItemTypes()
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
FullSpanUtil.onAttachedToRecyclerView(recyclerView, this, TYPE_HEADER)
}
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
super.onViewAttachedToWindow(holder)
FullSpanUtil.onViewAttachedToWindow(holder, this, TYPE_HEADER)
}
}
- (2) 在代码中添加
view.rv_tab_photo.addItemDecoration(
PinnedHeaderItemDecoration.Builder(TYPE_HEADER)
.disableHeaderClick(false)
.create()
)
3. 要点:
- 头部时间和照片均为list对象, 通过
MultiItemEntity
接口中的getItemType
自动识别为头部或者照片 - 将时间list和照片list合并, 按照时间戳, 进行倒序排列设置进adapter即可
4. 逻辑
-
获取手机全部照片对象
MultiPhotoEntity
, 对象实现MultiItemEntity
接口fun getLocalPhotosMulti(context: Context): List<MultiPhotoEntity> { val list = ArrayList<MultiPhotoEntity>() val projection = arrayOf( MediaStore.Images.Media.DATA, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.SIZE ) val where = (MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?") //指定格式 val whereArgs = arrayOf( "image/jpeg", "image/png", "image/jpg", "image/gif" ) val cursor = context.contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, where, whereArgs, MediaStore.Images.Media.DATE_MODIFIED + " desc " ) ?: return list //没有图片的时候反回0,所以不用try-catch while (cursor.moveToNext()) { val multiPhotoEntity = MultiPhotoEntity() val imageInfo = ImageInfo() //获取图片的名称 imageInfo.title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)) val data = cursor.getBlob(cursor.getColumnIndex(MediaStore.Images.Media.DATA)) val path = String(data, 0, data.size - 1) multiPhotoEntity.modifyDate = DateUtil.timeStampToString(File(path).lastModified(), "yyyy-MM-dd EEEE") multiPhotoEntity.timestamp = File(path).lastModified() imageInfo.modifyTimestamp = File(path).lastModified() imageInfo.modifyTimeString = DateUtil.timeStampToString(File(path).lastModified(), "yyyy-MM-dd EEEE") imageInfo.filePath = path imageInfo.fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.SIZE)) imageInfo.isChecked = false imageInfo.fileType = 6 multiPhotoEntity.imageInfo = imageInfo list.add(multiPhotoEntity) } cursor.close() return list }
-
通过手机照片对象的时间, 将其中的时间取出来组成
MultiHeaderEntity
头部对象(例如三张照片, 时间分别是2019-05-14, 2019-05-15, 2019-05-15, 则头部对象长度为2个)/** * 所有照片的时间, 获取时间集合, 转化为有时间的跟照片对象类型(均实现了MultiItemEntity接口)一样的头部对象 */ fun getHeaderInfo(context: Context): List<MultiHeaderEntity> { //获取本地所有的照片 val imageInfos: List<ImageInfo?>? = getLocalPhotos(context) val multiPhotoEntities = mutableListOf<MultiHeaderEntity>() if (imageInfos != null && imageInfos.isNotEmpty()) { for (i in 0 until imageInfos.size) { var isAdd = false if (multiPhotoEntities.size > 0) { for (j in 0 until multiPhotoEntities.size) { if ((multiPhotoEntities[j] as MultiHeaderEntity).header == imageInfos[i]?.modifyTimeString) { // (multiPhotoEntities[j] as MultiHeaderEntity).imageInfo = imageInfos[i] isAdd = true break } } } if (!isAdd) { val photoHeaderEntity = MultiHeaderEntity() photoHeaderEntity.header = (imageInfos[i]?.modifyTimeString) //时间戳转换为日期,去掉分时,将日期转为时间戳,因为是倒序排列,所以需要添加一天的长度,否则出现照片在时间头下面的情况 photoHeaderEntity.timestamp = DateUtil.dateToTimestamp(DateUtil.timeStampToString(imageInfos[i]?.modifyTimestamp!! + 1 * 24 * 60 * 60 * 1000, "yyyy-MM-dd")) // photoHeaderEntity.imageInfo = imageInfos[i] multiPhotoEntities.add(photoHeaderEntity) } } } return multiPhotoEntities }
-
合并头部list 和照片list
//获取所有头部list val headerList = PhotoUtil.getHeaderInfo(activity!!) //例长度80 //获取所有照片list val photosList = PhotoUtil.getLocalPhotosMulti(activity!!) //例长度为2000 //创建一个新集合,将头部和照片添加,并倒序排列 val list = mutableListOf<MultiItemEntityWithTimestamp>() //因为要用时间戳进行排列,所以需要获取时间戳,所以定义一个实现了getStamp的方法的MultiItemEntityWithTimestamp接口,该接口也继承MultiItemEntity list.addAll(headerList) list.addAll(photosList) //按照时间戳进行倒序排列 list.sortByDescending { it.getStamp() }