ListView无法获取高度问题:网络ImageView高度随宽度缩放不确定
解决ListView无法正确计算高度(含比例缩放网络ImageView)的问题
这问题我之前做项目时也踩过坑,核心原因就是ImageView加载网络图片时,初始高度为0,ListView没法提前预知它的最终高度,导致整个列表的高度计算出错,要么显示不全,要么滚动异常。下面给你几个实用的解决思路:
思路一:通过图片加载库提前计算目标高度
既然ImageView是按宽度比例缩放,我们可以先拿到图片的宽高比,再结合ImageView的实际宽度算出目标高度,动态设置给ImageView,让ListView能正确计算item高度:
以Glide为例,代码如下:
Glide.with(context) .asBitmap() .load(imageUrl) .addListener(object : RequestListener<Bitmap> { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean { return false } override fun onResourceReady(resource: Bitmap?, model: Any?, target: Target<Bitmap>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { resource?.let { // 获取ImageView的实际宽度(这里直接取屏幕宽度,因为你的ImageView是match_parent) val imgWidth = Resources.getSystem().displayMetrics.widthPixels // 计算图片宽高比 val aspectRatio = it.height.toFloat() / it.width.toFloat() // 算出ImageView的目标高度 val targetHeight = (imgWidth * aspectRatio).toInt() // 动态设置ImageView高度 val params = iv_intro_img.layoutParams params.height = targetHeight iv_intro_img.layoutParams = params // 通知ListView重新计算布局 (iv_intro_img.parent.parent as? ListView)?.requestLayout() } return false // 让Glide继续把图片加载到ImageView上 } }) .into(iv_intro_img)
思路二:自定义比例ImageView,重写测量逻辑
如果不想依赖图片加载库的回调,可以自定义一个ImageView,让它在测量阶段就按预设的宽高比算出高度:
public class RatioImageView extends ImageView { private float aspectRatio = 1.0f; // 默认宽高比1:1 public RatioImageView(Context context) { super(context); } public RatioImageView(Context context, AttributeSet attrs) { super(context, attrs); // 也可以通过自定义属性提前设置宽高比 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RatioImageView); aspectRatio = ta.getFloat(R.styleable.RatioImageView_aspectRatio, 1.0f); ta.recycle(); } // 拿到图片宽高比后调用这个方法更新 public void setAspectRatio(float ratio) { this.aspectRatio = ratio; requestLayout(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); // 按宽高比计算高度 int measuredHeight = (int) (measuredWidth * aspectRatio); setMeasuredDimension(measuredWidth, measuredHeight); } }
之后在Adapter里,拿到图片的宽高比后调用setAspectRatio(),ImageView就能自己算出正确高度,ListView也能跟着正确计算item的高度了。
思路三:换成RecyclerView(更省心的方案)
如果项目允许的话,直接把ListView换成RecyclerView会省事很多——RecyclerView的布局管理器(比如LinearLayoutManager)会自动处理item高度变化的情况,只要在图片加载完成后调用notifyItemChanged(position),RecyclerView就会重新测量并更新对应item的高度,不会出现整个列表高度计算错误的问题。
额外注意点
- 不管用哪种方法,都要确保图片加载完成后通知列表重新布局,不然可能还是会出现高度异常
- 尽量不要给ListView设置
wrap_content作为高度,优先用match_parent或者固定高度,配合上面的方法让item高度正确计算
内容的提问来源于stack exchange,提问作者jin.wang
相关产品推荐
相关产品推荐

