Framework源码面试六部曲:5.onMeasure测量原理
Posted 初一十五啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Framework源码面试六部曲:5.onMeasure测量原理相关的知识,希望对你有一定的参考价值。
前言
今天在电脑上翻出了很久之前整理笔记Framework
源码面试,Flutter
,以及一部分面试专题。拿出来温习一下。
今天先讲Framework
源码篇:
1.
Framework
源码面试:1.Activity
启动流程
2.Framework
源码面试:2.Binder
面试
3.Framework
源码面试:3.Handler
面试
4.Framework
源码面试:4.事件分发机制
5.Framework
源码面试:5.onMeasure
测量原理
6.Framework
源码面试:6.android
屏幕刷新机制
众所周知,自定义 ViewGroup
中这几个方法非常重要:onMeasure
, onLayout
。初学者学习自定义 View 时,想必对 onMeasure
比较困惑,onMeasure
是什么,为什么要测量,怎么测量?
1.1.1 onMeasure测量是什么? 为什么需要测量呢
测量的定义: 确定实际尺寸。
为什么需要测量: Android 中, View 的 layout_width layout_height
并不是固定值,它可以设置成 dp
、MATCH_PARENT
、WRAP_CONTENT
三种形式。
- 我们试想,如果用户设置了精确值 dp,那就好说,直接给 View 设置成精确的宽度,一旦用户给子 View 设置了
MATCH_PARENT
(匹配父窗体),子 View 的宽度应该是父窗体的宽度,而问题是子 View 并不知道父窗体多宽。- 为了解决这样的矛盾,Android 系统干脆规定:子 View 的宽高必须交给父 View 去测量。在测量时,父 View 会根据自己的尺寸和子 View 的
LayoutParams
,计算出一个MeasureSpec
(测量规则),也是父 View 对子 View 尺寸的期望。- 然后遍历调用子 View 的
measure(widthMeasureSpec,heightMeasureHeight)
进行实际测量。测量完成,子 View 的宽高就确定了,可以通过view.getMeasuredWidth()
方法获取。整个过程如下图所示。
1.1.2 能简单说下测量的过程吗
1.1.3 我们都知道测量中有三种模式 EXACTLY AT_MOST UNSPECIFIED 说下他们的意义
AT_MOST:最大模式
用这个模式去测量,并在测量时提供一个最大值,那么 View 就先以自己的内容为准,在不超过最大值的前提下,最终确定自己的尺寸
代码
int widthSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.AT_MOST);
// 第二个参数为高度的测量规则,写 0 表示省略
view.measure(widthSpec, 0);
UNSPECIFIED:不确定模式
用这个模式去测量, View 就会任意确定自己的尺寸,不管你传什么值进去都是没有意义。很少用,为了避免和
AT_MOST
搞混,暂时将它忽略。
int widthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
// 第二个参数为高度的测量规则,写 0 表示省略
view.measure(widthSpec, 0);
1.1.4 测量规则是什么呢 widthMeasureSpec,heightMeasureSpec 我们知道他们是32位,32位中代表的含义
widthMeasureSpec
和heightMeasureSpec
是测量规则- 是一个
int
类型,但是它并不是实际的尺寸,而是尺寸和测量模式的合成值。- 它在
int
类型的 32 位二进制位中,31-30 这两位表示模式,0~29 这三十位表示宽和高的实际值。- 通过
MeasureSpec
类提供的静态方法,我们可以从widthMeasureSpec
和heightMeasureSpec
中提取测量模式和期望尺寸。
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
1.1.5 如何确定的子类的测量模式
上面说了,父类测量子类是调用子 View 的
measure(widthMeasureSpec,heightMeasureHeight)
,这个两个测量widthMeasureSpec
规则是父类根据自己的宽度和子类的LayoutParams
计算出来的。那么到底怎么计算测量规则,看下面一张图就全明白了(注意相同的颜色)。
以上是关于Framework源码面试六部曲:5.onMeasure测量原理的主要内容,如果未能解决你的问题,请参考以下文章
Framework源码面试六部曲:5.onMeasure测量原理
Framework源码面试六部曲:1.activity启动流程