View的工作原理(一)——Measure
一、认识ViewRoot和DecorView
当Activity对象被创建的时候,会将DecorView添加到Window中,同时创建ViewRootImpl对象(ViewRoot对应于ViewRootImpl类),两者互相建立关系。
通过ViewRoot调用performTranversals开始绘制View,依次通过measure、layout、draw三个过程。如图

之后依次调用:performMeasure、performLayout、performDraw三个方法
二、DecorView的内容栏

①、上面是标题栏,下面是内容栏。 ②、通过setContentView所设置的布局文件加载到内容栏中(R.id.content) ③、如何获得内容栏:ViewGroup content = findViewById(R.id.content); ④、如何得到我们设置的View content.getChildAt(0);
三、MeasureSpec介绍
1.performMeasure中会调用measure方法,measure方法绘制自己的宽高,onMeasure方法会对所有子元素进行measure方法,依次类推,完成整个View树的遍历。
2.measure完成之后,可以通过getMeasureWidth和getMeasureHeight方法获取View测量后的宽高。
3.先要了解MeasureSpec:系统会将LayoutParams根据父容器的规则转换成对应的MeasureSpec,之后再根据measureSpec来测量出View的宽/高。
主要属性:SpecMode三种测量模式:
UNSPECIFIED(未指定,一般用于系统内部),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小,对应LayoutParams中的match_parent和具体数值
AT_MOST(至多),子元素至多达到指定大小的值,对应LayoutParams的wrap_content
SpecSize:某测量模式下的得到的大小。
主要方法:(根据源码,会将测量值打包,然后通过标识符解包)
1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一) 返回值是类型
2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小) 返回值是大小
3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式) 返回值是标识符,就是上两个方法的measureSpec
四、使用
一般View,其MeasureSpec由父容器的MeasureSpec和自身LayoutParams决定
1、(DecoreView的measureSpec由屏幕决定)先对DecoreView进行MeasureSpec创建:根据DecoreView的LayoutParams和屏幕的大小
放入MeasureSepc.makeMeasure()中(源码P179页),返回的spec(应该是标识符,通过MeasureSpec的get方法来获取放入的参数)。
2、ViewGroup的Measure方法
之后调用ViewGroup的measure()方法获取ViewGroup的范围(该方法是固定的,没办法继承),然后调用onMeasure()方法(该方法ViewGroup和View都没有重写,所以要自己重写该方法)。在onMeasure()中测量子View。
测量子View的方法有:
getChildAt(int index).可以拿到index上的子view。 通过getChildCount得到子view的数目,再循环遍历出子view。测量子View的wSpec,hSpec(结合子View的LayoutParams加上parent的Measure)。接着,childView.measure(int wSpec, int hSpec); //使用子view自身的测量方法
或者调用viewGroup的测量子view的方法:‘
//某一个子view,多宽,多高, 内部加上了viewGroup的padding值、margin值和传入的宽高wUsed、hUsed
measureChildWithMargins(subView, intwSpec, int wUsed, int hSpec, int hUsed);
源码解析:详见P180①
原理:获取childView的LayoutParams,然后调用getChildMeasure(P180 ②)方法获取childMeasureSpec()。
所以说该方法的主要功能,就是获取ViewGroup的宽高范围,和ViewGroup的padding及childView的margin,然后通过getChildMeasure()测量真实的childView的Spec
getChildMeasure()方法:
根据ViewGroup的Measure和padding相减获取可用范围。
之后根据parent及child的LayoutParams属性,制定childView的MeasureSpec
表格参照如下:

//所有子view 都是 多宽,多高, 内部调用了measureChild方法(P186 ②)
measureChildren(int wSpec, int hSpec);作用、获取所有子View除非View为GONE状态,其余都调用measureChild方法
//某一个子view,多宽,多高, 内部加上了viewGroup的padding值
measureChild(subView, int wSpec, int hSpec); (P187)
3、一般View的measure过程
详见源码(P184①):一般View的onMeasure方法不是遍历子元素(因为本身就是),作用是调用setMeasuredDimension()设置最终大小。
源码中有两个方法,getDefaultSize()方法:根据measureSpec决定最终的大小。
getSuggestedMinmumWidth/Height()作用:再根据设置的背景图和minWidth/Height宽高改变View的范围大小。
根据源码引出wrap_content设置无效,解决方法:(P186 设置默认宽、高)
4、LinearLayout部分源码探究(P188)
onMeasure()根据纵横,选择measure方法(这里选择wrap_content和verital时),之后遍历子View利用mTopLength获取总高度,最后LinearLayout通过measure方法选定总宽高。
引出:在onCreate、onStart、onResume方法中均无法得到某个View的宽高,原因:View的measure过程和Activity的生命周期不同步执行。
所以解决方法:
(一)、重写onWindowFocusChanges()方法,在该方法中调用getMeasureWidth/Height()方法。原因:只有当View初始化完毕才会回调该方法
作用:当Activity的窗口得到或者数去焦点都会被调用一次。
(二)、view.post(runnable)将一个runnable投递到一个消息队列的尾部。
View的工作原理(一)——Measure的更多相关文章
- 梳理源码中 View 的工作原理
欢迎Follow我的GitHub, 关注我的掘金. 在View的工作过程中, 执行三大流程完成显示, 测量(measure)流程, 布局(layout)流程, 绘制(draw)流程. 从perform ...
- Android艺术开发探索第四章——View的工作原理(上)
这章就比较好玩了,主要介绍一下View的工作原理,还有自定义View的实现方法,在Android中,View是一个很重要的角色,简单来说,View是Android中视觉的呈现,在界面上Android提 ...
- 《Android开发艺术探索》读书笔记 (4) 第4章 View的工作原理
本节和<Android群英传>中的第3章Android控件架构与自定义控件详解有关系,建议先阅读该章的总结 第4章 View的工作原理 4.1 初始ViewRoot和DecorView ( ...
- Android学习笔记View的工作原理
自定义View,也可以称为自定义控件,通过自定义View可以使得控件实现各种定制的效果. 实现自定义View,需要掌握View的底层工作原理,比如View的测量过程.布局流程以及绘制流程,除此之外,还 ...
- View的工作原理(一) 总览View的工作流程
View的工作原理(一) 总览View的工作流程 学习自 <Android开发艺术探索> 简书博主-丶蓝天白云梦 Overview 从本章开始,开始学习View的工作原理,包括View的 ...
- Android之view的工作原理2
学习内容 View的底层工作原理,比如View的测量流程.布局流程以及绘制流程:以及常见的View回调方法:熟悉掌握前面的知识后,自定义View的时候也会更加的得心应手. 4.1 初识ViewRoot ...
- Android艺术开发探索第四章——View的工作原理(下)
Android艺术开发探索第四章--View的工作原理(下) 我们上篇BB了这么多,这篇就多多少少要来点实战了,上篇主席叫我多点自己的理解,那我就多点真诚,少点套路了,老司机,开车吧! 我们这一篇就扯 ...
- Android 中View的工作原理
Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...
- 四、View的工作原理
1.ViewRoot和DecorView ViewRoot对应于ViewRootImpl类,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过ViewRoot来完 ...
随机推荐
- struts2注解驱动 零配置
一.配置web.xml<filter><filter-name>struts2</filter-name><filter-class>org.apach ...
- 使导出excle文档实现ALT+Enter的效果()
JAVA中输入什么转义字符,使导出excle文档实现ALT+Enter的效果?或者有没有其他方法可以实现. 20 JAVA中输入什么转义字符,使导出excle文档实现ALT+Enter的效果?或者有没 ...
- [C++程序设计]内置函数
注意: 可以在声明函数和定义函数时同时写 inline,也可以只在其中一处声明inline,效果相同,都能按内置函数处理. 使用内置函数可以节省运行时间,但却增加了目标 程序的长度.因此一般只将规模很 ...
- wdcp/wdlinux 在 UBUNTU/linux 中安装失败原因之创建用户
根本原因在于安装时创建的用户www 使用了和ubuntu已创建的用户,冲突了自然创建不了用户. 你可以修改lanmp.sh脚本中创建www用户时的代码,将1000改为其他数字. 也可以修改当前用户的U ...
- python 核心编程第六章课后题自己做的答案
6–6. 字符串.创建一个 string.strip()的替代函数:接受一个字符串,去掉它前面和后面的 空格(如果使用 string.*strip()函数那本练习就没有意义了) 'Take a str ...
- css制作简单下拉菜单
要点:定位,隐藏,显示. (一)先建一个两次列表 <ul id="ul1"> <li>首页</li> <li>第二页 <ul& ...
- Kafka与Logstash的数据采集
Kafka与Logstash的数据采集 基于Logstash跑通Kafka还是需要注意很多东西,最重要的就是理解Kafka的原理. Logstash工作原理 由于Kafka采用解耦的设计思想,并非原始 ...
- C# 多线程的自动管理(线程池) 基于Task的方式
C# 多线程的自动管理(线程池) 在多线程的程序中,经常会出现两种情况: 1. 应用程序中线程把大部分的时间花费在等待状态,等待某个事件发生,然后给予响应.这一般使用 ThreadPool(线程 ...
- ArcGIS for WPF 访问外部资源
原文 http://www.cnblogs.com/wdysunflower/archive/2011/07/14/2105584.html ArcGIS for WPF 访问外部资源 应用背景: 因 ...
- 【转】Linux里如何查找文件内容
原文网址:http://blog.chinaunix.net/uid-25266990-id-199887.html Linux查找文件内容的常用命令方法. 从文件内容查找匹配指定字符串的行: $ g ...