您的位置:首页 > 产品设计 > UI/UE

Android MeasuerSpec的由来及使用

2016-04-06 11:38 357 查看
含义:MeasuerSpec是parent传递给child的一组测量值(size)和模式(mode)的组合。

使用场景:经常我们会在child的onMeasure(int widthMeasureSpec,int heightMeasureSpec)这个函数中来对spec进行处理,用于确定child的长和宽。



这里我们看到MeasureSpec有3中测量模式:

MeasureSpec.AT_MOST :child最多达到parent的大小,这一类通常归于"wrap_content"。

MeasureSpec.EXACTLY:child的大小是一个确定的值,这一类通常归于"match_parent"或者是一个确定的值。

MeasureSpec.UNSPECIFED:这个几乎不用,未指定,child可以得到自己想要的任何大小。

Measure的makeMeasureSpec,getMode,getSize我这里就不多说了,很简单就是一个位运算。

说了半天,到底这个widthMeasureSpec和heightMeasureSpec怎么来的呢?这就需要看看源码。

我们知道View的测量和绘制都是通过它的parent来触发的,所以直接进ViewGroup

切入点就是measure:



这里我们又看到一个parentWidthMeasureSpec和parentHeightSpec,这里我们先不管,大概知道这个是它的parent给它的spec。

继续进入函数:



可以看到,这里在switch(mode)和我们处理view的onMeasure差不多。

继续向下:



到这里,spec就已经组合好了,下一步应该是传递给child计算了。




到这里为止,viewgroup的测量就算完成了。接下来就是交给child自己计算,也就回到了,我们最初的onMeasure函数中。

上面我们还说到了这个parentWidthMeasureSpec和parentHeightSpec,其实也就是当前viewgroup的parent给它的测量模式和值。遵循上面的步骤,一模一样。

所以以后像遇到这个问题,解决思路和办法就很简单了。

View view=getLayoutInflater().inflate(R.layout.layout_item, null);

Toast.makeText(MainActivity.this, "view_w="+view.getMeasuredWidth()+","+view.getLayoutParams(), 0).show();



为啥view的宽度为0,layoutparams为null?

view的宽度为0,很明显:就是view没有measure,因为我们是从一个xml文件中pull解析出来的一个view,它没有parent更没有parent测量,所以为0.

解决办法就是measure,view.measure(0,0)一下;我们传0,0,最终也就是view自己测量自己。这里还有一个layoutparams为null,为啥呢?

我们知道layoutParams是parent给child的布局参数。在view的源码中我们看到



还有get,set方法



我们回到viewGroup中。



这里我们看到addview会传递一个params,这个params怎么来的呢?



这里我们看到了child的layoutparams是在addview中赋值的,所以上面的layoutinflate的view因为没有parent所以就没有layoutparams。

解决办法:



欢迎大家指正和批评!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息