RecyclerView将高度改为wrap_content后无法显示图片的问题咨询
这个问题我之前在使用旧版support库的RecyclerView时也碰到过,核心原因是早期的RecyclerView(比如support.v7版本中23.2.0之前的版本)对wrap_content的高度支持存在bug:当RecyclerView的高度设为wrap_content时,它无法正确计算子项Item的高度,导致包含图片的Item没有被正确测量和绘制,所以图片就显示不出来;而设为match_parent时,RecyclerView会占满父布局空间,能正常触发子项的测量流程,图片就能正常显示。
针对这个问题,有几个靠谱的解决办法:
1. 升级RecyclerView库(推荐方案)
Google在support库23.2.0版本开始修复了RecyclerView的wrap_content计算问题,如果你还在用旧版的android.support.v7.widget.RecyclerView,建议直接升级到最新的support库,或者迁移到AndroidX的androidx.recyclerview.widget.RecyclerView,这样不用额外写代码就能解决问题。
2. 自定义LayoutManager强制计算高度(适用于无法升级库的场景)
如果因为项目限制不能升级库,可以自定义一个LayoutManager,重写onMeasure方法来手动计算RecyclerView的高度。以LinearLayoutManager为例:
public class WrapContentLinearLayoutManager extends LinearLayoutManager { public WrapContentLinearLayoutManager(Context context) { super(context); } public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { super(context, orientation, reverseLayout); } public WrapContentLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { int height = 0; for (int i = 0; i < getItemCount(); i++) { View child = recycler.getViewForPosition(i); measureChild(child, widthSpec, heightSpec); int childHeight = child.getMeasuredHeight(); height += childHeight + getDecoratedTop(child) + getDecoratedBottom(child); } height += getPaddingTop() + getPaddingBottom(); setMeasuredDimension(View.MeasureSpec.getSize(widthSpec), height); } }
然后在代码中给RecyclerView设置这个自定义的LayoutManager:
RecyclerView rcView = findViewById(R.id.rcView); rcView.setLayoutManager(new WrapContentLinearLayoutManager(this));
3. 确保Item布局中的图片有明确的尺寸约束
另外检查一下你的Item布局里的ImageView,确保它有明确的尺寸设置(比如固定的android:layout_width和android:layout_height),或者设置android:adjustViewBounds="true"并配合android:scaleType(比如centerCrop、fitXY),避免因为图片本身尺寸不确定导致Item高度无法被正确计算。
内容的提问来源于stack exchange,提问作者Prashant Abdare

