android view measure方法

最近项目需要,一位同事架构RecyclerView嵌套RecyclerView实现一个需求,而且哇啦啦啦写了一整天,结果显示一看,嵌套的RecyclerView不显示,不管怎么调试也不显示。。。这个问题其实和我们之前ListView嵌套ListView不显示一样,就是在建立的View嵌套树中,嵌套的ListView测量没有明确的测量依据,导致测量的大小直接返回0了,所以需要让RecyclerView重新测量一下,关键代码是:

1
2
int widthtSpecTitle=View.MeasureSpec.makeMeasureSpec(Interge.MAXVALUE >> 2,View.MeasureSpec.AT_MOST);
holder.itemView.measure(widthtSpecTitle,View.MeasureSpec.UNSPECIFIED);

意思就是告诉测量的View,对于宽width,尽量自己测量吧,对与长,我没有限制,你是多少就给多少吧。同时采用的测量是结合DataAdapter一起对itemView进行测量的,主要代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static int getItemHeight(Context context, ItemData data, int viewType) {
RelativeLayout parent = new RelativeLayout(context);
DataAdapter mAdapter = new DataAdapter();

ItemHolder holder;
holder = (ItemHolder) mAdapter.onCreateViewHolder(parent, viewType);
mAdapter.onBindViewHolder(holder,data.get(position));
int measureHeight = 0;
WindowManager wm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
int width = wm.getDefaultDisplay().getWidth();
int widthSpecTitle=View.MeasureSpec.makeMeasureSpec(width,View.MeasureSpec.AT_MOST);
holder.itemView.measure(widthSpecTitle,View.MeasureSpec.UNSPECIFIED);
measureHeight = holder.itemView.getMeasuredHeight();

return measureHeight;
}

调用View的measure会简介调用ViewGroup的onMeasure,View的measure的源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
。。。。
if (cacheIndex < 0 || sIgnoreMeasureCache) {
// measure ourselves, this should set the measured dimension flag back
// 重点onMeasure方法
onMeasure(widthMeasureSpec, heightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
} else {
long value = mMeasureCache.valueAt(cacheIndex);
// Casting a long to int drops the high 32 bits, no mask needed
setMeasuredDimensionRaw((int) (value >> 32), (int) value);
mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}

。。。。
}

但是测量的结果总是不对,要不太大了,要不太小了,总结如下:
1 如果对于子视图的显示主要依赖负空间的大小然后按照比例计算的,Measure方法的调用需要添加适当的大小。
2 对于ImageView,如果没有设置默认的图片,等待网络加载在显示,默认的大小是为0的,源码如下,所以对于ImageVIew的测量需要特殊处理一下,单独做测量处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
。。。。
resolveUri();
int w;
int h;

// Desired aspect ratio of the view's contents (not including padding)
float desiredAspect = 0.0f;

// We are allowed to change the view's width
boolean resizeWidth = false;

// We are allowed to change the view's height
boolean resizeHeight = false;

final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

if (mDrawable == null) {
// If no drawable, its intrinsic size is 0.
mDrawableWidth = -1;
mDrawableHeight = -1;
w = h = 0; //没有图片就直接返回大小为0
} else {
w = mDrawableWidth;
h = mDrawableHeight;
if (w <= 0) w = 1;
if (h <= 0) h = 1;

// We are supposed to adjust view bounds to match the aspect
// ratio of our drawable. See if that is possible.
if (mAdjustViewBounds) {
resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;

desiredAspect = (float) w / (float) h;
}
}

。。。。。
}

~~~本人能力有限,难免有理解不透彻的地方,有什么问题欢迎指出,感谢~~~

文章目录
,