Android RecyclerView中超长图片显示黑块但仍占用空间问题咨询
Android RecyclerView超长图片加载显示黑块解决方案
问题根因
Android 系统的OpenGL渲染对单个纹理的最大尺寸有限制,大部分设备的最大纹理高度为2048px或4096px,当图片实际渲染高度超过该阈值时,系统无法正常渲染就会出现黑块,仅占用布局空间不显示内容,这和你设置的负边距关联度较低,负边距仅调整布局位置不会放大实际渲染的图片尺寸。
可行解决方案
方案1:Glide加载时限制最大尺寸
加载图片时通过
override()方法限制最大高度,避免图片实际加载尺寸超过硬件纹理阈值,推荐限制高度为4096px以下,代码示例如下:// 4096为大部分设备支持的最大纹理高度,可兼容绝大多数场景 val maxRenderHeight = 4096 Glide .with(context) .load(fileUrl) .listener(object : RequestListener<Drawable> { override fun onLoadFailed( e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean ): Boolean { return false } override fun onResourceReady( resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean ): Boolean { holder.picLoadIcon.visibility = View.GONE return false } }) .apply(glideOptions) .fitCenter() // 宽度保持自适应,高度限制为最大渲染高度 .override(Target.SIZE_ORIGINAL, maxRenderHeight) .into(holder.image)方案2:使用分片加载的长图控件
替换原生
ImageView为专门支持超大图分片渲染的控件,它会将超大图拆分为多个小纹理分片加载,不会触发单纹理尺寸限制,天然支持超长图正常显示,加载代码示例如下:Glide.with(context) .asBitmap() .load(fileUrl) .into(object : CustomTarget<Bitmap>() { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { holder.picLoadIcon.visibility = View.GONE holder.image.setImage(ImageSource.bitmap(resource)) } override fun onLoadCleared(placeholder: Drawable?) {} })方案3:用Glide裁剪替代负边距裁水印
你当前用负边距隐藏水印的逻辑,可以替换为Glide的自定义裁剪变换,加载时直接裁剪掉底部水印区域,减少实际渲染的图片总高度,也能避免超出尺寸限制:
// 自定义裁剪变换,裁剪掉底部cutOff高度的水印区域 class CropBottomTransformation(private val cropHeight: Int) : BitmapTransformation() { override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { val newHeight = toTransform.height - cropHeight return Bitmap.createBitmap(toTransform, 0, 0, toTransform.width, newHeight) } override fun updateDiskCacheKey(messageDigest: MessageDigest) {} } // Glide加载时添加变换即可,无需再设置负边距 Glide.with(context) .load(fileUrl) .transform(CropBottomTransformation(cutOff)) // 其余加载逻辑保持不变 .into(holder.image)
额外优化建议
你当前布局中ImageView添加了app:layout_constraintxxx系列属性,而父布局是RelativeLayout,这部分属性完全无效,可以直接删除减少冗余代码。
内容的提问来源于stack exchange,提问作者TheGreatCornholio
相关产品推荐
相关产品推荐

