measureChildren作品
无论是在改写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作品的更多相关文章
- 【读书笔记《Bootstrap 实战》】2.作品展示站点
假设我们已经想好了要给自己的作品弄一个在线站点.一如既往,时间紧迫.我们需要快一点,但作品展示效果又必须专业.当然,站点还得是响应式的,能够在各种设备上正常浏览,因为这是我们向目标客户推销时的卖点.这 ...
- Vue.js起手式+Vue小作品实战
本文是小羊根据Vue.js文档进行解读的第一篇文章,主要内容涵盖Vue.js的基础部分的知识的,文章顺序基本按照官方文档的顺序,每个知识点现附上代码,然后根据代码给予个人的一些理解,最后还放上在线编辑 ...
- [官方作品] 关于ES4的设首页问题
[官方作品] 关于ES4的设首页问题 Skyfree 发表于 2013-2-10 21:55:03 https://www.itsk.com/thread-254503-1-1.html 关于ES4设 ...
- 15个前卫的 HTML5 & CSS3 网页设计作品
今天,我们编译收集一组使用 HTML5 和 CSS3 制作的精美网站.在此集合中,你可以看到平面设计,网页设计,作品集和企业网站设计实例. 响应式设计和基于 HTML5 & CSS3 编码的网 ...
- 全球酷站秀:15个顶尖的 CSS3 网站作品
每天有数以百计的网站推出,其中很多优秀网站被推荐到 CSS 画廊供大家评分和评论,这对于网页设计师来说是很好的灵感来源.今天,我们选择了15个来自全球各地的 CSS3 网站设计作品, 它们都是赢得 C ...
- 关注经典:CSS Awards 获奖网站作品赏析《第一季》
每天都有很多新的网站推出,其中不乏一些设计极其优秀的作品.这个系列的文章,我为大家挑选了2012年赢得 CSS Awards 大奖的50个最佳网站.这些鼓舞人心的网站作品代表了网页设计的最高水平,相信 ...
- CodePen 作品秀:Canvas 粒子效果文本动画
作品名称——Shape Shifter,基于 Canvas 的粒子图形变换实验.在页面下方的输入框输入文本,上面就会进行变换出对应的粒子效果文本动画. CodePen 作品秀系列向大家展示来自 Cod ...
- 【Bootstrap】2.作品展示站点
假设我们已经想好了要给自己的作品弄一个在线站点.一如既往,时间紧迫.我们需要快一点,但作品展示效果又必须专业.当然,站点还得是响应式的,能够在各种设备上正常浏览,因为这是我们向目标客户推销时的卖点.这 ...
- Cool!12幅由小图片组成的创意图像重组作品
这里分享15幅创意插图作品,这些创意插图作品都是有成千上万的小图片组成的,很多创意广告会采用这个形式的设计.下面这组创意作品的作者是 Charis Tsevis,来自希腊的视觉设计师,擅长图像重组的创 ...
随机推荐
- 2015广东工业大学ACM学校巡回赛 I 游戏高手 (如压力dp)
Problem I: 游戏王 Description 小学的时候,Stubird很喜欢玩游戏王.有一天,他发现了一个绝佳的连锁组合,这个连锁组合须要6张卡. 但是他一张都没有,但是他的那些朋友们有.只 ...
- 【C语言探索之旅】 第二部分第五课:预处理
内容简介 1.课程大纲 2.第二部分第五课: 预处理 3.第二部分第六课预告: 创建你自己的变量类型 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会公布答案.还会带大家用C语 ...
- Hello ASP.NET5
2015年11月30日, ASP.NET 5 RC1 已经发布,本文尝试了一下ASP.NET5项目的创见一发布到IIS.开发环境,win10 64位,visual studio2015(已更新upda ...
- ASP.NET2.0组件控件开发视频 初体验
原文:ASP.NET2.0组件控件开发视频 初体验 ASP.NET2.0组件控件开发视频 初体验 录了视频,质量不是很好,大家体验下.我会重新录制的 如果不清楚,可以看看http://v.youku. ...
- Mysql入门到精通数据表的操作
变更表 ALTER TABLE tb_name; 1.加入场 ALTER TABLE tb_name ADD 字段名字 字段类型 约束条件 [FIRST/AFTER 字段名称] 1>加入user ...
- c++日历v1.12版
////////////////////////////新增信息修改功能,未完善. #include<iostream> #include <string> #include& ...
- 2C 产品的本质是人性,2B 产品的背后是业务(转)
本文作者李源是 BLUES 原来做 YY 语音客户端产品时候的同事,原来针对 YY 语音的游戏用户做 2C 的 PC 客户端产品和 APP,后来到某品牌手机做 2B 的后台系统.以下文章,是作者经历了 ...
- ios新开发语言swift 新手教程
http://gashero.iteye.com/blog/2075324 视频教程:http://edu.51cto.com/lesson/id-26464.html
- SQLServer数据类型优先级对性能的影响
原文:SQLServer数据类型优先级对性能的影响 译自: http://www.mssqltips.com/sqlservertip/2749/sql-server-data-type-preced ...
- Repeater在无数据记录时显示暂无数据
原文:Repeater在无数据记录时显示暂无数据 方法就是在FooterTemplate加个Label并根据repeater.Items.Count判断是否有记录.关键代码如下: <Footer ...