• View树的measure流程
  • View的measures时序图
  • View布局流程之measure
    • measure过程

      • View的measure过程
      • ViewGroup的measure过程
      • FrameLayout的measure过程

View树的measure流程图如下:

View树的measure时序图:

View的measure过程

View的measure方法如下:

View.java

这是个final方法, 子类不能重写, 主要是在里面会调用onMeasure方法.

此处有一个优化, 就是把MeasureSpec保存, 下次执行measure方法时如果measureSpec不变就不执行measure流程, 除非设置了PFLAG_FORCE_LAYOUT标志, 这个标志就是在requestLayout里面设置的.

onMeasure之后会检查PFLAG_MEASURED_DIMENSION_SET标志, 也就是要求的onMeasure方法里面要调用setMeasuredDimensition方法(注意此方法设置的是尺寸不是MeasureSpec).

看默认的onMeasure方法



这里调用 setMeasuredDimension方法,默认通过getDefaultSize计算宽高. 其中 在看此方法之前,先看getSuggestedMinimumxxx()方法:



getSuggestedMinimumWidth是此View的最小尺寸, 一般是背景图片的尺寸和minWidth/minHeight属性值较大的. 当然也可以重写此方法返回自定义值.

然后看getDefaultSize()方法:



不限定大小则返回自己大小, 否则返回父容器限定的最大值.

结合上面的MeasureSpec我们知道, 如果View的LayoutParams使用wrap_content, 那么它的SpecMode是AT_MOST模式. 这种情况下此View大小是父容器的剩余空间大小, 和match_parent一致了. 因此一般情况下自定义View的子类都需要重新onMeasure方法.

再看setMeasuredDimension方法:

这个方法决定了当前View的大小,也是一个final方法,写自定义控件大小时,重写onMeasure方法,最终都会调用此方法。到此一次最基础的元素View的measure过程就完成了。

View实际是挂在decorView树上的树枝,而且measure是递归的,所以每个View都需要measure。一般能够嵌套的View一般都是ViewGroup的子类,所以在ViewGroup中定义了measureChildren, measureChild, measureChildWithMargins方法来对子视图进行测量,measureChildren内部实质只是循环调用measureChild,measureChild和measureChildWithMargins的区别就是是否把margin和padding也作为子视图的大小。下面分析ViewGroup的measure过程

ViewGroup的measure过程

ViewGroup的measure过程除了完成自己的measure, 还需要遍历左右的子元素的measure方法. 虽然ViewGroup提供了measureChildren方法遍历每个子元素进行measure, 但是不同的布局类型有不同的measure逻辑, 有的ViewGroup自身尺寸依赖子元素的尺寸(如LinearLayout), 有的部分依赖子元素尺寸(如ScrollView), 因此需要子类实现onMeasure具体过程.

measureChildren方法:

measureChild方法:

measureChildWithMargins方法:

虽然不同ViewGroup的measure流程不一致, 但是measure单个子View的逻辑基本是一样的, 就是上面的measureChildWidthMargins方法, 因此ViewGroup子类基本都使用此方法来measure子元素.

以上几个方法都会调用getChildMeasureSpec()方法:

补充 MeasureSpec.makeMeasureSpec(resultSize, resultMode),也可以看上一篇

Android View框架总结(三)View工作原理



从这个逻辑,我们可以知道child的specMode,specSize是通过其父View提供的MeasureSpec参数得到specMode和specSize,然后根据计算出来的specMode以及子View的childDimension(layout_width或layout_height)来计算自身的measureSpec,如果其本身包含子视图,则计算出来的measureSpec将作为调用其子视图measure函数的参数,同时也作为自身调用setMeasuredDimension的参数,如果其不包含子视图则默认情况下最终会调用onMeasure的默认实现,并最终调用到setMeasuredDimension。

FrameLayout的measure过程





上面方法总结如下:

  • 如果传入的SpecMode是EXACTLY, FrameLayout自身的尺寸不依赖子元素, 或者子元素是wrap_content(有AT_MOST限制), 那么一次遍历即可完成, 子元素兄弟之间没有依赖关系, 都是调用measureChildWidthMargins即可;
  • 否则需要遍历子元素measure后, 取最大的尺寸(但不超过父容器限制)为自身尺寸, 然后重新measure那些宽或高是match_parent的子元素, 再次遍历过程中SpecMode变成了EXACTLY.

第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易

Android View框架总结(四)View布局流程之Measure的更多相关文章

  1. Android View框架总结(五)View布局流程之Layout

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52216195 View树的Layout流程 View的Layout时序图 View布局 ...

  2. Android学习笔记_3_四种布局

    Android布局是应用界面开发的重要一环,在Android中,共有四种布局方式, 分别是:FrameLayout( 帧布局 ).LinearLayout (线性布局).TableLayout(表格布 ...

  3. Android View框架总结(六)View布局流程之Draw过程

    请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52236145 View的Draw时序图 ViewRootImpl.p ...

  4. Android艺术探索第四 view的自定义

    一.初见View View的层级关系(Veiw到底分成几层,自定义view是从那一层开始绘制的) R:Veiw树的结构如下 ,自定义View是从DecorView开始的;DecorView是View树 ...

  5. Android应用层View绘制流程之measure,layout,draw三步曲

    概述 上一篇博文对DecorView和ViewRootImpl的关系进行了剖析,这篇文章主要是来剖析View绘制的三个基本流程:measure,layout,draw.仅仅有把这三个基本流程搞清楚了, ...

  6. Android显示框架:自定义View实践之绘制篇

    文章目录 一 View 二 Paint 2.1 颜色处理 2.2 文字处理 2.3 特殊处理 三 Canvas 3.1 界面绘制 3.2 范围裁切 3.3 集合变换 四 Path 4.1 添加图形 4 ...

  7. Android View 的绘制流程之 Layout 和 Draw 过程详解 (二)

    View 的绘制系列文章: Android View 的绘制流程之 Measure 过程详解 (一) Android View 绘制流程之 DecorView 与 ViewRootImpl 在上一篇  ...

  8. View学习(四)-View的绘制(draw)过程

    View的draw过程相比之于measrue过程,也是比较简单的.并且在我们自定义View时,也经常需要重写onDraw方法,来绘制出我们要实现的效果. 如之前的文章所说,绘制的流程也是起始于View ...

  9. Android 应用框架 —— 组件

    本文内容根据个人自学整理记录,理解不当之处,希望大家批评指正,大家相互学习,写学习归纳,写博客是个好习惯,希望能够坚持下去. 在前一篇文章当中介绍了Android 的系统框架,主要是为了让大家对And ...

随机推荐

  1. [Noi2016]区间

    题目描述 在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn].现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置.换句话说,就是使得存在一个 x,使得对于每一 ...

  2. 【NOIP2017 OFO】

    ·奇怪的标题可能预示着这一篇博文不是讲算法或者分享题目的吧. [一只情绪化的兔子]      今年的11月12日出奇地比去年温暖.两场比赛结束后的我们在临走前去尝试了OFO共享单车,在成都电子科技大学 ...

  3. 51nod 1035:最长的循环节

    1035 最长的循环节 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题   正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求< ...

  4. vue-cli2.9.1如何自动打开浏览器及实现手机调试

    在vue-cli2.9.1以前我们运行 "npm run dev" 程序会自动打开浏览器进行调试,而且在手机浏览器输入 "IP地址:8080" 能实现在手机端的 ...

  5. Java并发编程之并发工具类

    CountDownLatch CountDownLatch可以用于一个或多个线程等待其他线程完成操作. 示例代码 private static CountDownLatch c = new Count ...

  6. jmeter分布式测试远程连接失败

    jmeter分布式部署其实很简单.但今天测试的时候发现了一个坑,远程连接一直失败. 原因:服务器上部署了slave,而这台服务器上有多个网卡.举个例子:ip分别为:192.168.100.6,10.1 ...

  7. Response ServletContext 中文乱码 Request 编码 请求行 共享数据 转发重定向

    Day35  Response 1.1.1 ServletContext概念 u 项目的管理者(上下文对象),服务器启动时,会为每一个项目创建一个对应的ServletContext对象. 1.1.2  ...

  8. Numpy函数学习--genfromtxt函数

    genfromtxt函数 今天学习时遇到了genfromtxt函数 world_alcohol = numpy.genfromtxt("world_alcohol.txt",del ...

  9. PHP 5 Array 函数

    PHP Array 简介 PHP Array 函数允许您访问并操作数组. 支持简单的数组和多维数组. 安装 PHP Array 函数是 PHP 核心的组成部分.无需安装即可使用这些函数. PHP 5 ...

  10. 防止SpringMVC拦截器拦截js等静态资源文件

    SpringMVC提供<mvc:resources>来设置静态资源,但是增加该设置如果采用通配符的方式增加拦截器的话仍然会被拦截器拦截,可采用如下方案进行解决: 方案一.拦截器中增加针对静 ...