无论是在改写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. jquery省市区三级联动

    jquery省市区三级联动(数据来源国家统计局官网)内附源码下载 很久很久没有写博了. 今天更新了项目的省市区三级联动数据,更新后最新的海南三沙都有,分享给所有需要的小伙伴们... JQUERY + ...

  2. 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

    原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API [索引页][源码下载] 返璞归真 asp.net mvc (10) - asp.net ...

  3. Amazon SQS简单介绍 上篇

    SQS即Simple Queue Service, 是一个分布式的消息队列服务,使用它很easy,消息队列服务能够用来buffer burst, 使整个服务异步处理,不要求组件始终可用. 开发者最初使 ...

  4. MSSQL基础

    前言 最近看到一些关于sql的汇总博客,觉得还是很不错的.于是心血来潮,也想写一篇自己对这方面的一些认识(主要是点出一下自己比较少用demo写的,一般都是直接改设计时的,例如建表.该字段名). 一.数 ...

  5. java.lang.IllegalStateException: ActionBarImpl can only be used with a compatible window decor layou

    于Activity调用它们的定义dialog事件ActionBarImpl can only be used with a compatible window decor layout异常, 解决方法 ...

  6. Linux核心regulator建筑和准备

    电源引入的物种 (百度百科)LDO这是low dropout regulator,这意味着低压差线性稳压器.它相比于传统的线性调节器.传统的线性稳压器.例如78xx系列芯片需要输入电压比输出电压高2v ...

  7. mfc配置GDI+有106个错误

    mfc配置GDI+有106个错误,处理如下,参考http://bbs.csdn.net/topics/380054079 一开始#include...放在stdafx.h里有错误,后来上面修改好了,放 ...

  8. 云梯vpn

    刚和大饼合买了一个云梯的vpn 表示可以把俺的优惠连接放出来了 貌似必须是新注册用户才能够享用优惠 http://protizi.com/?r=5e3fecd7eae558ec 把云梯推荐给朋友们 让 ...

  9. 【玩转微信公众平台六】 构建新浪SAEserver

    连接急于继续发言. ------本文主要介绍介绍如何设置 新浪SAEserver.猛戳 http://sae.sina.com.cn/1.先自己注冊一个账号,假设有新浪的账号,微博之类的都能够直接拿来 ...

  10. ExtJS4 动态生成grid出口excel(纯粹的接待)

    搜索相当长的时间,寻找一些样本,因为我刚开始学习的原因,大多数人不知道怎么用.. 他曾在源代码.搞到现在终于实现了主下载.. 表的采集格不重复下载一个小BUG,一个使用grid初始化发生的BUG 以下 ...