无论是在改写View依然是ViewGroup什么时候。特别ViewGrop什么时候,通常是不可避免的重写onMeasure方法,我们一定会调用setMeasuredDimension()将測量好的宽高值传递进去。也不免调用measureChildren方法。来測量全部的子View的大小,以下我们看看measureChildren方法是怎样工作的。

这对我们重写onMeasure无疑是非常有帮助的。由于一般我们都会看到这一行代码

// 计算出全部的childView的宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);

可是它究竟測量到什么程度,满足不满足我们自己定义ViewGroup对以下一系列child尺寸的測量需求,不知道这个我们写代码就心里没底。

所以我们有必要扒出它的老底来看看。由此来决定我们能否够直接使用这种方法,还是因为我们有很多其它的效果要实现,有很多其它的因素须要考虑。这种方法不能满足需求,须要自己写方法来測量child。

同一时候我们在有必要又一次写方法来測量child的时候,我们也要从自带方法的思路開始扩展。

说了一大堆。总之这个问题非常重要。

以下要了解它的工作原理,我们还是要来看看源代码:

(一)首先是measureChildren

 /** 
 * 遍历全部的子view去測量自己(跳过GONE类型View) 
 * @param widthMeasureSpec 从父容器传递给子容器的布局需求(宽)
 * @param heightMeasureSpec 从父容器传递给子容器的布局需求(高)
 */  
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
final int size = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < size; ++i) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
}

这部分非常easy,也就是遍历全部的子View,假设View的状态不是GONE就调用measureChild去进行下一步的測量。

(二)所以我们再来看一下measureChild



/**
* 測量单个视图。将宽高和padding加在一起后交给getChildMeasureSpec去获得终于的測量值
* @param child 须要測量的子视图
<pre name="code" class="java"> * @param widthMeasureSpec 从父容器传递给子容器的布局需求(宽)
 * @param heightMeasureSpec 从父容器传递给子容器的布局需求(高)

*/ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { // 取得子视图的布局參数 final LayoutParams lp = child.getLayoutParams(); // 通过getChildMeasureSpec获取终于的宽高具体測量值 final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); // 将计算好的宽高具体測量值传入measure方法。完毕最后的測量 child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}


这种方法就是对一个子视图进行測量。当中一个重要的方法就是getChildMeasureSpec()。

(三)所以我们再来看一下getChildMeasureSpec

/**
*
* 结合父view的MeasureSpec与子view的LayoutParams信息去找到最好的结果
* (子view的确切大小由双方面共同决定:父view的MeasureSpec 子view的LayoutParams属性)
*
* @param spec 父view的MeasureSpec
* @param padding view当前尺寸的的内边距和外边距(padding,margin)
* @param childDimension child在当前尺寸下的布局參数宽高值(LayoutParam.width,height)
*/
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
//父view的模式和大小
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec); //通过父view计算出的子view = 父大小-边距(父要求的大小。但子view不一定用这个值)
int size = Math.max(0, specSize - padding); //子view想要的实际大小和模式(须要计算)
int resultSize = 0;
int resultMode = 0; //通过1.父view的MeasureSpec 2.子view的LayoutParams属性这两点来确定子view的大小
switch (specMode) {
// 当父view的模式为EXACITY时,父view强加给子view确切的值
case MeasureSpec.EXACTLY:
// 当子view的LayoutParams>0也就是有确切的值
if (childDimension >= 0) {
//子view大小为子自身所赋的值,模式大小为EXACTLY
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
// 当子view的LayoutParams为MATCH_PARENT时(-1)
} else if (childDimension == LayoutParams.MATCH_PARENT) {
//子view大小为父view大小,模式为EXACTLY
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
// 当子view的LayoutParams为WRAP_CONTENT时(-2)
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
//子view决定自己的大小。但最大不能超过父view,模式为AT_MOST
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break; // 当父view的模式为AT_MOST时,父view强加给子view一个最大的值。
case MeasureSpec.AT_MOST:
// 道理同上
if (childDimension >= 0) {
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break; // 当父view的模式为UNSPECIFIED时,子view为想要的值
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0) {
// 子view大小为子自身所赋的值
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
} else if (childDimension == LayoutParams.MATCH_PARENT) {
// 由于父view为UNSPECIFIED,所以MATCH_PARENT的话子类大小为0
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
} else if (childDimension == LayoutParams.WRAP_CONTENT) {
// 由于父view为UNSPECIFIED,所以WRAP_CONTENT的话子类大小为0
resultSize = 0;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
}
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}

总而言之,这些推断和设置事实上就是依据三种模式以及传入的尺寸要求,还有须要考虑的padding和margin之后。比較全面的计算出了一个測量值,了解了这些之后我们就能够确定什么时候须要自己写关于子视图的測量部分。什么时候我们仅仅须要简单的一行代码:

// 计算出全部的childView的宽和高
measureChildren(widthMeasureSpec, heightMeasureSpec);

就能够满足我们的需求了,所以一切还是按需来处理。

在我个人看来,这种方法考虑的比我最初想象的要全面多了,看来除了有比較特殊的需求,大部分的时候都是能够直接使用这种方法的。这还是省了不少事的。

假设您对我提到的模式或者是重写过程不大了解的,详细的关于重写onMeasure内容请详见我的另外一篇博客:

http://blog.csdn.net/sunmc1204953974/article/details/38454267

希望大家能有所收获,我也是学生。有什么写的不好的地方还请多多不吝赐教!

版权声明:本文博客原创文章,博客,未经同意,不得转载。

measureChildren作品的更多相关文章

  1. 【读书笔记《Bootstrap 实战》】2.作品展示站点

    假设我们已经想好了要给自己的作品弄一个在线站点.一如既往,时间紧迫.我们需要快一点,但作品展示效果又必须专业.当然,站点还得是响应式的,能够在各种设备上正常浏览,因为这是我们向目标客户推销时的卖点.这 ...

  2. Vue.js起手式+Vue小作品实战

    本文是小羊根据Vue.js文档进行解读的第一篇文章,主要内容涵盖Vue.js的基础部分的知识的,文章顺序基本按照官方文档的顺序,每个知识点现附上代码,然后根据代码给予个人的一些理解,最后还放上在线编辑 ...

  3. [官方作品] 关于ES4的设首页问题

    [官方作品] 关于ES4的设首页问题 Skyfree 发表于 2013-2-10 21:55:03 https://www.itsk.com/thread-254503-1-1.html 关于ES4设 ...

  4. 15个前卫的 HTML5 & CSS3 网页设计作品

    今天,我们编译收集一组使用 HTML5 和 CSS3 制作的精美网站.在此集合中,你可以看到平面设计,网页设计,作品集和企业网站设计实例. 响应式设计和基于 HTML5 & CSS3 编码的网 ...

  5. 全球酷站秀:15个顶尖的 CSS3 网站作品

    每天有数以百计的网站推出,其中很多优秀网站被推荐到 CSS 画廊供大家评分和评论,这对于网页设计师来说是很好的灵感来源.今天,我们选择了15个来自全球各地的 CSS3 网站设计作品, 它们都是赢得 C ...

  6. 关注经典:CSS Awards 获奖网站作品赏析《第一季》

    每天都有很多新的网站推出,其中不乏一些设计极其优秀的作品.这个系列的文章,我为大家挑选了2012年赢得 CSS Awards 大奖的50个最佳网站.这些鼓舞人心的网站作品代表了网页设计的最高水平,相信 ...

  7. CodePen 作品秀:Canvas 粒子效果文本动画

    作品名称——Shape Shifter,基于 Canvas 的粒子图形变换实验.在页面下方的输入框输入文本,上面就会进行变换出对应的粒子效果文本动画. CodePen 作品秀系列向大家展示来自 Cod ...

  8. 【Bootstrap】2.作品展示站点

    假设我们已经想好了要给自己的作品弄一个在线站点.一如既往,时间紧迫.我们需要快一点,但作品展示效果又必须专业.当然,站点还得是响应式的,能够在各种设备上正常浏览,因为这是我们向目标客户推销时的卖点.这 ...

  9. Cool!12幅由小图片组成的创意图像重组作品

    这里分享15幅创意插图作品,这些创意插图作品都是有成千上万的小图片组成的,很多创意广告会采用这个形式的设计.下面这组创意作品的作者是 Charis Tsevis,来自希腊的视觉设计师,擅长图像重组的创 ...

随机推荐

  1. BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 分块

    分块大法好 2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MB Submit: 2938  Solved: 13 ...

  2. cassandra 服务启动流程

    cassandra 服务启动流程 1.  setup 1)   CassandraDaemon ->main publicstaticvoidmain(String[]args) { insta ...

  3. JVM内存结构、垃圾回收那点事(转)

    翻看电脑的文件夹,无意看到了9月份在公司做的一次分享,浏览了一下"婆婆特",发现自己在ppt上的写的引导性问题自己也不能确切的回答出来,哎,知识这东西,平时不常用的没些日子就生疏了 ...

  4. 矩阵求逆c++达到

    高斯消元法能够用来找出一个可逆矩阵的逆矩阵.设A 为一个N * N的矩阵,其逆矩阵可被两个分块矩阵表示出来.将一个N * N单位矩阵 放在A 的右手边,形成一个N * 2N的分块矩阵B = [A,I] ...

  5. POJ 2828 Buy Tickets(排队问题,线段树应用)

    POJ 2828 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2828 Buy Tickets 题意:  排队买票时候插队.  给出一些数对,分别代表某个人的想要插入的位 ...

  6. javascript 比量str今天的日期是,参数diff

    function isToday(str) { var d = new Date(str.replace(/-/g, "/")); var todaysDate = new Dat ...

  7. Android提高第二篇之SurfaceView的基本使用

    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 上次介绍MediaPlayer的时候略微介绍了SurfaceView,SurfaceView因为能够直接从内存 ...

  8. 使用hql当异常查询:Xxx is not mapped[from Xxx where ...]

    采用当今项目hql询问.出现    QingAoCenterInfo is not mapped[from QingAoCenterInfo where...] 显然地Hibernate映射关系出现了 ...

  9. curl 要么 file_get_contents 获得授权页面的方法的必要性

    今天,需要工作,需要使用 curl / file_get_contents 获得授权的必要性(Authorization)的页面内容.解决后写了这篇文章分享给大家. php curl 扩展,可以在se ...

  10. BZOJ 3505 CQOI 2014 数三角形 数学

    标题效果:到m*n该网络格,问:有网络格是一个三角形的顶点的数目. 思维:数学.首先计算所有三个相同的,不.然后,在上线的一个点失去了三个点是其中.需要注意的是,答案开放long long. CODE ...