聊天应用反向RecyclerView使用Glide加载URL图片时如何阻止自动滚动?
问题根因
该异常的本质是反向配置(reverseLayout=true/setStackFromEnd(true))的RecyclerView,在异步图片加载完成后触发ImageView尺寸变更,进而触发RecyclerView重布局时,默认会将尺寸变化的Item滚动到可视区域,导致自动跳转。Fresco无此问题是因为它默认会提前占用和图片匹配的View尺寸,不会触发加载后的View尺寸变更。
可行解决方案
方案1:固定ImageView尺寸(优先推荐)
提前和服务端约定图片返回的宽高参数,聊天列表的ImageView加载图片前,先根据接口返回的宽高动态设置好匹配布局的固定宽高,再调用Glide加载,从根源避免加载后的尺寸变化。
示例代码:
// 从消息元数据中提前获取图片原始宽高 val originalWidth = message.imageWidth val originalHeight = message.imageHeight // 适配聊天区域最大宽度,避免图片超出屏幕 val maxChatImgWidth = resources.getDimensionPixelSize(R.dimen.chat_image_max_width) val finalHeight = (originalHeight * maxChatImgWidth / originalWidth.toFloat()).toInt() // 先设置ImageView固定尺寸 imageView.layoutParams.apply { width = maxChatImgWidth height = finalHeight } // 再调用Glide加载 Glide.with(context) .load(message.imageUrl) .override(maxChatImgWidth, finalHeight) .into(imageView)
方案2:禁用RecyclerView的自动滚动动画
如果无法提前拿到图片宽高,可以修改LayoutManager配置,禁用Item变化触发的自动滚动:
// 自定义LayoutManager,关闭预测动画 recyclerView.layoutManager = object : LinearLayoutManager(context, VERTICAL, true) { override fun supportsPredictiveItemAnimations(): Boolean { return false } } // 同时关闭RecyclerView默认Item动画 recyclerView.itemAnimator = null
该方案代价是会取消列表的Item插入、更新动画,适合对聊天列表动画要求不高的场景。
方案3:对齐占位图与实际图片比例
如果你的业务场景下所有聊天图片的宽高比例固定,可以设置相同比例的占位图,保证图片加载前后ImageView尺寸无变化:
Glide.with(context) .load(message.imageUrl) .placeholder(R.drawable.chat_image_placeholder) // 占位图宽高比例与实际图片完全一致 .fitCenter() .into(imageView)
内容的提问来源于stack exchange,提问作者Sudhansu
相关产品推荐
相关产品推荐

