先看效果图
需求
- 类似微博九宫图一样,单张图片显示比例(此处具体先省略)
- 2张图和4张图片显示 格子列数为4宫格
需要的库
com.github.bumptech.glide:glide:4.9.0
com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.44
大概思路
- 数据请求 省略(我用的酷安的数据热门评论接口)
- 根据评论中图片数据设置图片
RecyclerView
等SpanCount
,每一条评论都含有一个展示图片的RecycleView
,再设置ItemDecoration
- 对不同的图片个数的
ViewHolder
设置不同的type
上代码
CmsStyleCommentNormalViewHolder
:类中
if (!TextUtils.isEmpty(dateItem.pic) && dateItem.picArr != null) {
val nineImageList = arrayListOf<NineImageBean>()
var spanCount = 0
dateItem.picArr?.let { it1 ->
spanCount = if (it1.size == 1) {
1
} else if (it1.size == 2 || it1.size == 4) {
2
} else {
3
}
it1.forEachIndexed { index, s ->
nineImageList.add(NineImageBean().apply {
this.isGif = StringUtils.isGifUrl(s)
this.url = s
this.positionAdapter = index
if (spanCount == 1) {
this.type = NineImageBean.LargeImageType
} else {
this.type = NineImageBean.SmallImageType
}
})
}
}
val cmsChildImageNineAdapter: CmsChildImageNineAdapter
val adapterTag = nineImageRv.tag
if (adapterTag is CmsChildImageNineAdapter) {
cmsChildImageNineAdapter = adapterTag
} else {
cmsChildImageNineAdapter = CmsChildImageNineAdapter(ArrayList())
nineImageRv.apply {
cmsChildImageNineAdapter.bindToRecyclerView(this)
this.isNestedScrollingEnabled = false
this.setHasFixedSize(true)
this.tag = cmsChildImageNineAdapter
}
cmsChildImageNineAdapter.setOnItemClickListener { adapter, _, position ->
val pictureBeanList = ArrayList<PictureBean>()
for (item in adapter.data) {
if (item is NineImageBean) {
pictureBeanList.add(PictureBean().apply {
this.originalUrl = item.url
})
}
}
if (pictureBeanList.isNotEmpty()) {
LaunchNormalUtils.startPictureActivity(mContext, pictureBeanList, position)
}
}
}
nineImageRv.apply {
this.layoutParams.width = if (spanCount == 4 || spanCount == 2) {
singleImageWidth.toInt() * 2
} else if (spanCount == 1) {
ViewGroup.LayoutParams.WRAP_CONTENT
} else {
ViewGroup.LayoutParams.MATCH_PARENT
}
for (i in 0 until this.itemDecorationCount) {
this.removeItemDecorationAt(i)
}
this.layoutManager = GridLayoutManager(mContext, spanCount)
this.addItemDecoration(RecyclerViewItemDividerHelper.getNineImageAdapterDividerItem(mContext, spanCount, this, 16f))
}
cmsChildImageNineAdapter.setNewData(nineImageList)
nineImageRv.visibility = View.VISIBLE
} else {
nineImageRv.visibility = View.GONE
}
}
- 上面代码位于一个评论ViewHolder类
- CmsChildImageNineAdapter:
class CmsChildImageNineAdapter(data: MutableList<NineImageBean>?): BaseMultiItemQuickAdapter<NineImageBean, BaseViewHolder>(data) {
init {
addItemType(NineImageBean.emptyType, R.layout.item_multi_not_found)
addItemType(NineImageBean.SmallImageType, R.layout.item_multi_nine_image_small)
addItemType(NineImageBean.LargeImageType, R.layout.item_multi_nine_image_large)
}
override fun convert(helper: BaseViewHolder, item: NineImageBean) {
var associatedObject = helper.associatedObject
when (item.itemType) {
NineImageBean.SmallImageType -> {
if (associatedObject == null) {
associatedObject = NineSmallViewHolder(mContext, helper)
helper.associatedObject = associatedObject
}
if (associatedObject is NineSmallViewHolder) {
associatedObject.updateView(item)
}
}
NineImageBean.LargeImageType -> {
if (associatedObject == null) {
associatedObject = NineLargeViewHolder(mContext, helper)
helper.associatedObject = associatedObject
}
if (associatedObject is NineLargeViewHolder) {
associatedObject.updateView(item)
}
}
}
}
-
NineSmallViewHolder
:
class NineSmallViewHolder(val mContext: Context, val baseViewHolder: BaseViewHolder) : IBaseViewMultiHolder<NineImageBean>(baseViewHolder.itemView) {
private val smallImageIv: CustomGifImageView = itemView.findViewById(R.id.small_image_iv)
private val smallGifFlagRtv: RoundTextView = itemView.findViewById(R.id.small_gif_flag_rtv)
private var gifHandler: GifHandler? = null
private inner class ParamTag {
var isFirstFrame = true
var isAlwaysPlayerGif = true
}
override fun updateView(dateItem: NineImageBean) {
super.updateView(dateItem)
smallImageIv.apply {
if (dateItem.isGif && !this.isGifRunning()) {
smallGifFlagRtv.visibility = View.VISIBLE
} else {
smallGifFlagRtv.visibility = View.GONE
}
if (!dateItem.isGif) {
loadNormalImage(dateItem)
} else {
if (!this.isGifRunning()) {
loadGifImage(ParamTag().apply {
this.isFirstFrame = true
})
}
}
}
}
private fun loadNormalImage(dateItem: NineImageBean) {
ImageLoader.Builder(mContext)
.getRequestManager()
.asBitmap()
.load(dateItem.url)
.apply(ImageLoader.defaultRequestOptions(R.color.placeholder_color))
.into(smallImageIv)
}
- 我粘贴的事项目中代码,我也懒得删除了,所以
CustomGifImageView
就用imageview
就行,也不用判断GIF加载什么的,就gilde直接加载就OK -
NineLargeViewHolder
:
class NineLargeViewHolder(val mContext: Context, val baseViewHolder: BaseViewHolder) : IBaseViewMultiHolder<NineImageBean>(baseViewHolder.itemView) {
private val largeIv: MatrixScaleImageView = itemView.findViewById(R.id.large_iv)
private val largeFlagRtv: RoundTextView = itemView.findViewById(R.id.large_flag_rtv)
private val gifFlagRtv: RoundTextView = itemView.findViewById(R.id.gif_flag_rtv)
override fun updateView(dateItem: NineImageBean) {
super.updateView(dateItem)
largeFlagRtv.visibility = View.GONE
gifFlagRtv.visibility = View.GONE
dateItem.picImageSize?.apply {
val matrixScaleHelper = MatrixScaleHelper(this[0].toFloat(), this[1].toFloat())
largeIv.apply {
gifFlagRtv.visibility = if (dateItem.isGif && !this.isGifRunning()) {
View.VISIBLE
} else {
View.GONE
}
largeFlagRtv.visibility = if (matrixScaleHelper.isLongBitmap && !dateItem.isGif) {
View.VISIBLE
} else {
View.GONE
}
if (!dateItem.isGif) {
loadNormalImage()
} else {
if (!this.isGifRunning()) {
loadGifImage(true)
}
}
}
}
}
override fun changeTheme(theme: Theme) {
super.changeTheme(theme)
largeFlagRtv.setBackgroundColor(ColorUtils.getThemeColor(mContext, R.attr.colorAccent))
gifFlagRtv.setBackgroundColor(ColorUtils.getThemeColor(mContext, R.attr.colorAccent))
}
fun startPlayerGif() {
val nineImageBean = getItemTagDate() as? NineImageBean ?: return
if (nineImageBean.isGif) {
loadGifImage(false)
}
}
fun stopPlayerGif() {
val nineImageBean = getItemTagDate() as? NineImageBean ?: return
if (nineImageBean.isGif) {
loadGifImage(true)
}
}
private fun loadNormalImage() {
val nineImageBean = getItemTagDate()
if (nineImageBean is NineImageBean) {
val picImageSize = nineImageBean.picImageSize ?: return
val matrixScaleHelper = MatrixScaleHelper(picImageSize[0].toFloat(), picImageSize[1].toFloat())
ImageLoader.Builder(mContext, nineImageBean.url)
.setTransition(ImageLoader.defaultTransitionOptions())
.setRequestOptions(ImageLoader.defaultRequestOptions(R.color.placeholder_color)
.transform(matrixScaleHelper.getCropTransformation(largeIv)))
.build(largeIv)
}
}
- GIF 代码我就不粘贴了,其中一部分,这个viewHolder比较特殊,一问微博中单个图片比较特殊,是有比例显示的,大长图显示上半部分,普通图片等比例缩放,
MatrixScaleHelper
类就是一个等比缩放类 - 粘贴的是部分代码和思路,全部代码整理起来比较麻烦,实现效果比较多
- 后面会陆续贴出来实现微博九宫图 GIF图片依次播放,还有单张图片等比缩放,以及换肤(不重启应用)过程中RecycleView的处理