想写这部分内容已经很久了,但是每次写的时候总感觉自己讲的不够清楚,但是感觉这种事情真的不能拖,越拖越解决不了,所以,Let‘s go!好好理一理LinearLayout的measure的原理,也就是测量逻辑吧。当然,我并不想贴源码,因为一帖源码,容易让博客本身的篇幅变的非常冗长,晦涩和难懂。

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (mOrientation == VERTICAL) {measureVertical(widthMeasureSpec, heightMeasureSpec);} else {measureHorizontal(widthMeasureSpec, heightMeasureSpec);}}

LinearLayout存在横向和纵向两种布局,但是在onMeasure()时并没有什么本质上的区别,仅仅是左右和上下互换而已,因此为了减少篇幅和提升效率,我们这里就对纵向布局(mOrientation==VERTICAL)的情况进行分析。相信看懂了纵向的原理之后,横向的原理也就不是什么难事了。

在LinearLayout这样的布局中,对于显示的资源就像是一种零和博弈,即子视图多获得显示空间是基于其他子视图失去显示空间的前提之下的。在这种情况下,根据在xml或者代码中所定义的布局相关参数解析所得的LayoutParam,我们可以将子视图分为两类:weight类型和非weight类型。

为什么这么分类呢?因为高度layout_height=0,weight>0的子视图比较特殊,他需要知道父视图中总共有多少layout_height=0,weight>0的子视图,然后和这些子视图按照weight比例瓜分显示空间。这个时候非weight类型的子视图已经把按照xml拿走自己所需的显示空间了。

对于非weight的情况的空间分配,遵从的就是先到先得的原则,稍有不同的是他们抢占的方式不同而已:

  • MATCH_PARENT:拿走剩下所有的可用空间

  • WRAP_CONTENT:如果可用空间大于子视图内部空间,则子视图拿走自身大小的空间;否则子视图拿走全部剩余空间

  • 具体数值:如果可用空间大于数值大小,则子视图拿走该数值大小的空间;否则子视图拿走全部剩余空间。但是有一点需要注意,对于指定数值小于0或者过大的情况,那么资源会怎么分配呢?留个悬念,下次再讲,因为正常情况下,也没有人会专门把视图的高度设置为负值或者特别大。

核心的思想基本就是这样了,我感觉抓住核心思想的优先级应当永远是高于一切的。接下来我们将相对详细地对LinearLayout中的测量过程进行分析,而且我也并不打算贴出过多的代码,因为我认为既然我已经打算写博客了,我就应该更多地写一些自己从代码上获得到的东西,而不应该单纯只是代码本身。这就和已经既然有了答案,还需要老师的原因是一样的。

我们一直知道了子视图拿取父视图的两种方式,但是拿取父视图的空间资源始终需要有一个前提,那就是,至少我们需要知道父视图有多少剩余的空间资源。父视图一般通过如下的三种模式来告诉子视图,其所能使用的空间资源大小:

  1. AT_MOST+SIZE:父视图当前的高度还不确定,并且父视图的高度测量很有可能需要依赖子视图的高度,所以父视图就给子视图一个最大的限定高度,子视图在进行测量的时候高度不能超过这个高度

  2. EXACTLY+SIZE:父视图当前的高度确定,然后允许子视图在这个尺寸里自由发挥

  3. UNSPECIFIED:父视图不对子视图的高度进行限制,所以只指定模式,不指定大小,这种类型的出现的情况不多,最常见的出现场景就是在ScrollView。因为ScrollView的子视图需要有滚动的效果,要是像之前的两种模式一样直接把子视图的高度限制在不超过父视图的前提下,那么滚动的效果肯定也就实现不了了。

上述所说的父视图的三种模式和子视图的三种模式相结合就能以递归的方式完成视图的测量,每一个子视图都是通过onMeasure(int,int)方法来获取到其横向和纵向的测量模式和尺寸的,模式和尺寸的递归推导可以结合我上面所说和下面这张图表来综合理解。

我们往往需要进行两次遍历从而确定所有子视图的尺寸,因为如果有多个子视图的模式为height=0并且weight>0的情况,在未遍历完所有的子视图的前提下,是无法知道到底有多少子试图需要与当前的子视图共同分享空间资源。

因此我们需要在第一次遍历子视图的时候,统计好所有的子视图所需要的高度,对于非weight>0的情况来说其实非常简单,只需要按照先到先得的原则予以分配空间资源即可。但是对于weight>0的情况,我们还是需要通过wrap_content的方式测量出其本身空间并基于此为其预订空间。因为根据上面的表格我们可以看见,对于具体数值的尺寸测量结果都是EXACTLY+childSize,而0+weight>0的模式,在实际上其实也就是传入具体的数值,这样会导致测量占用的结果为0,所以就需要通过在这种情况下将height设置为wrap_content的方式来进行空间资源的测量工作。

在第一轮子视图遍历完成之后,我们就能得到LinearLayout中的所有视图所占用的总尺寸,以及所有0+weight>0的情况子视图的weight总和。在前面我们对于0+weight>0模式的子视图通过wrap_contet的方式为其分配了空间。

对于父视图的测量模式为EXACTLY和AT_MOST的情况,0+weight>0的子视图会按照weight比例将剩余的空间填满,这里我们就需要根据我们之前实际上获得的所有试图所占用尺寸和onMeasure(int,int)方法所提供参数中MeasureSpec中所提供的size进行比较,多退少补,从而在第二次测量的时候达到0+weight>0的视图刚好填充完剩余空间的目的。

相对的,对于父视图的测量模式为UNSPECIFIED的情况,因为父视图对于子视图的高度并没有任何限制,也就没有所谓的填充完剩下所有可用空间的说法,这个时候的我们就通过临时将layout_height设置为wrap_content的方式从而先为每个0+weight>0的子视图占取对应的空间资源,等到第二轮遍历的时候再根据这些额外占据的资源和每个子视图的weight占比来为他们分配对应的实际空间资源。

其实在这里我们已经能够窥见一丝玄机,为什么google不建议进行多层嵌套,因为每一层的每一个子视图都有可能两次遍历,这样就导致了onMeasure(int,int)的时间复杂度随着嵌套层级的增加指数级增加。

LinearLayout测量原理解析:onMeasure(int,int)相关推荐

  1. Android onMeasure()测量流程解析

    Android onMeasure()测量流程解析 文章目录 Android onMeasure()测量流程解析 前言 布局与绘制流程文章 组件测量的那些结论 一.MeasureSpec:测量规则 二 ...

  2. 无法解析构造函数‘Employee(int,java.lang.String,java.lang.String,int,com.kuang.pojo.Department)‘

    前言:在写这篇博客的时候,本来博客名字打算叫:"在给Java伪造数据库里面的伪数据的相关字段插入数据时,插入失败,是什么原因导致的?",后来思前想后,还是决定直接拷贝使用编译器上面 ...

  3. PT100测量温度电路设计原理解析

    1.模块简介: 本模块可将PT100传感器信号经电桥测量放大输出,模块载有8位单片机处理器,通过此单片机的10位ADC对放大后的传感器信号采样,并通过程序计算出PT100阻值,采用查表法(查电阻对应温 ...

  4. void (*f(int, void (*)(int)))(int) 函数解析

    函数指针 今天与几个同学看到了一个函数指针定义: void (*f(int, void (*)(int)))(int) 以前在C trap pit fails里面见过,但是文章里面介绍的很详细,但是往 ...

  5. Android View绘制原理解析

    概述 本篇文章主要讲述View是如何在Android源码中产生的,以便于我们能够更好的去自定义一些控件,大体上是按照View绘制的流程来走步骤,在追踪源码之前我们先了解几个基础知识.来看下面的这张图: ...

  6. Android 插件换肤原理解析

    转至:http://blog.csdn.net/jiangwei0910410003/article/details/47679843 一.前言 今天又到周末了,感觉时间过的很快呀.又要写blog了. ...

  7. jetpack compose原理解析

    目录 jetpack compose原理解析 jetpack compse 声明式ui开发 原理分析 整体框架介绍 compose LayoutNode布局介绍 @Composeable注解实现细节 ...

  8. Tomcat 架构原理解析到架构设计借鉴

    ‍ 点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 Tomcat 架构原理解析到架构设计借鉴 Tomcat 发展这 ...

  9. 秋色园QBlog技术原理解析:Web之页面处理-内容填充(八)

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

最新文章

  1. SD--根据订单创建发票(相关的函数列表的介绍系列篇(3))
  2. 2017.5.23 -- 学习记录
  3. GDOI2018 总结
  4. 为最快动脉线诊断 铁科院联合第四范式完成高铁智能化巡检应用
  5. servlet和action的区别
  6. Echarts在手机端y轴数据过大,显示不全
  7. SHA384-算法解密
  8. Makefile.am和makefile.in生成Makefile
  9. 一些sql语句的详细解释
  10. mri计算机系统,MRI设备
  11. 面试时如何做自我介绍?聪明的应聘者只聚焦1点
  12. 前端速成:双月Java之旅(week5)_day4
  13. 计算机网络与综合布线系统设计,谈计算机网络综合布线系统设计
  14. 用手机把纸质文件扫描成pdf的方法分享,不能错过哦。
  15. 正数的平均值(调用函数)
  16. 基于云服务器 B/S模式 JavaWeb RFID 图书借阅管理系统
  17. UltraEdit 21.30.1006.0 繁体中文破解版(功能最强的文本编辑器)
  18. linux 查看服务器资源(cpu型号、cpu数量、内存大小、磁盘空间)
  19. 用Altium Designer软件绘制一个stm32最小系统的电路原理图
  20. 【PHP渗透技巧拓展】————3、LFI、RFI、PHP封装协议安全问题学习

热门文章

  1. Git命令比较两个分支commit 差异
  2. 场地测量的方法和程序_建筑施工测量的内容与方法
  3. Spring中@Autowired和@Resource区别
  4. 什么是负边沿触发_晶闸管的导通条件是什么 晶闸管(可控硅)检测方法
  5. centos7 安装git_如何在 CentOS 7 上挂载 Amazon EFS 文件系统?
  6. linux a文本编辑大全,Linux sed 命令 - Linux文档编辑命令大全
  7. npm 卸载_手把手教你创建一个NPM包
  8. 计算机硬盘怎么增加e盘和f盘,如何在我的电脑里新建一个磁盘区
  9. incon函数图像c语言,[转载]c语言经典题目
  10. laravel 5.5 的相关字符串辅助函数