将RecyclerView的宽高属性设置为“wrap_content”
来源:互联网 发布:淘宝网站首页源代码 编辑:程序博客网 时间:2024/05/17 07:44
前言
最近,在使用RecyclerView时遇到一个问题,就是将RecyclerView的高度设置为“wrap_content”时,控件实际测量高度为”match_parent”,为什么会出现这种问题呢?RecyclerView设置如下:
<android.support.v7.widget.RecyclerView android:id="@+id/sv_rv" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/darker_gray"></android.support.v7.widget.RecyclerView>
recyclerView = (RecyclerView)findViewById(R.id.sv_rv);recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));recyclerView.setAdapter(new RvAdapter());
而实际显示效果如下:
正文
一般来说,出现这种问题是因为高度测量问题,所以先查看RecyclerView的onMeasure方法,如下:
@Override protected void onMeasure(int widthSpec, int heightSpec) { if (mAdapterUpdateDuringMeasure) { eatRequestLayout(); processAdapterUpdatesAndSetAnimationFlags(); if (mState.mRunPredictiveAnimations) { // TODO: try to provide a better approach. // When RV decides to run predictive animations, we need to measure in pre-layout // state so that pre-layout pass results in correct layout. // On the other hand, this will prevent the layout manager from resizing properly. mState.mInPreLayout = true; } else { // consume remaining updates to provide a consistent state with the layout pass. mAdapterHelper.consumeUpdatesInOnePass(); mState.mInPreLayout = false; } mAdapterUpdateDuringMeasure = false; resumeRequestLayout(false); } if (mAdapter != null) { mState.mItemCount = mAdapter.getItemCount(); } else { mState.mItemCount = 0; } if (mLayout == null) { defaultOnMeasure(widthSpec, heightSpec); } else { mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec); } mState.mInPreLayout = false; // clear }
重要代码:
if (mLayout == null) { defaultOnMeasure(widthSpec, heightSpec); } else { mLayout.onMeasure(mRecycler, mState, widthSpec, heightSpec); }}
可以发现当RecyclerView设置LayoutManager时,RecyclerView的测量高度由所选择的LayoutManager决定。由于上文所选择的LayoutManager为LinearLayoutManager,故查看其源码的onMeasure函数,然而并没找到,那就查看其父类的onMeasure函数。
public void onMeasure(Recycler recycler, State state, int widthSpec, int heightSpec) { mRecyclerView.defaultOnMeasure(widthSpec, heightSpec);}
然后查看defaultOnMeasure函数,可以发现其并未对子item进行高度测量,所以导致其实测高度异常。故而要纠正此问题,需要重写LayoutManager的onMeasure函数。
如下,是我自己写的一个简单的LayoutManager子类,继承自LinearLayoutManager,仅作抛砖引玉之用:
package how.th.ridelib.RvLayoutManager;import android.content.Context;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;public class RecyclerLayoutManager extends LinearLayoutManager { public RecyclerLayoutManager(Context context){ super(context); } @Override public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { int itemCount = state.getItemCount(); int measuredWidth = 0; int measuredHeight = 0; int heightSize = View.MeasureSpec.getSize(heightSpec); for(int i = 0; i < itemCount; i ++){ View view = recycler.getViewForPosition(i); if(view != null){ RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams)view.getLayoutParams(); int margin = layoutParams.bottomMargin + layoutParams.topMargin; measuredWidth = View.MeasureSpec.getSize(widthSpec); view.measure(widthSpec, View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); switch (layoutParams.height){ case RecyclerView.LayoutParams.WRAP_CONTENT: measuredHeight += (getDecoratedMeasuredHeight(view) + margin); break; case RecyclerView.LayoutParams.MATCH_PARENT: default: measuredHeight += (layoutParams.height + margin); break; } } } if(measuredHeight > heightSize) super.onMeasure(recycler, state, widthSpec, heightSpec); else setMeasuredDimension(measuredWidth, measuredHeight); }}
实际使用:
recyclerView = (RecyclerView)findViewById(R.id.sv_rv);recyclerView.setLayoutManager(new RecyclerLayoutManager(getApplicationContext()));recyclerView.setAdapter(new RvAdapter());
实际效果:
0 0
- 将RecyclerView的宽高属性设置为“wrap_content”
- Android 中CheckBox设置background为一张图片并且宽高属性为wrap_content时图片被拉伸
- AppCompat主题下 button 宽高设置wrap_content属性无效的原因
- GridView 设置其高度属性为 wrap_content
- 一句话解决RecyclerView 高度设置wrap_content 无作用的bug
- RecyclerView wrap_content
- 【android】解决Viewpager设置高度为wrap_content无效的方法
- 解决ViewPager中RecyclerView的高度设为wrap_content无效的问题
- LisView、GridView、RecyclerView的高度wrap_content
- 设置bitmap的宽高,同时将bitmap转换为file对象
- 设置wrap_content属性后,按键延迟响应?
- ”属性不能设置为“Int64”值。必须将该属性设置为类型为“Int32”的非 null 值。
- RecyclerView常见问题解决方案,RecyclerView嵌套自动滚动,RecyclerView 高度设置wrap_content 无作用等问题
- View在属性为wrap_content/match_parent时获取宽高不准确的解决办法
- TextView设置wrap_content时,使其宽高适应文字内容大小而不是适应background大小
- 为RecyclerView设置emptyView
- 有效的解决ListView宽度设置为wrap_content还是占满整行的问题
- TextView 获取自适应 wrap_content 的宽高 Android 获得view的宽和高
- 详解YUV数据格式
- java学习---new的对象怎么被内存回收
- 最长公共子序列
- GCC 参数详解
- CentOS 7 安装教程、硬盘分区、LVM、网络配置、软件源配置、制作
- 将RecyclerView的宽高属性设置为“wrap_content”
- action函数详解(自定义action)
- 个位数与个位数的积
- Eclipse使用技巧 - 5. Eclipse代码自动补全失效解决办法
- vim的基本配置
- UICollectionViewFlowLayout备忘录
- 获取上周时间
- jdk8新特性
- Android 消息机制 以及Message、Handler、Message Queue、Looper之间的关系。