Framework源码面试——onMeasure测量原理

76 篇文章 4 订阅
15 篇文章 0 订阅

众所周知,自定义 ViewGroup 中这几个方法非常重要:onMeasure, onLayout。初学者学习自定义 View 时,想必对 onMeasure 比较困惑,onMeasure是什么,为什么要测量,怎么测量?

1. onMeasure测量是什么? 为什么需要测量呢

测量的定义:确定实际尺寸。

为什么需要测量: Android 中, View 的 layout_width layout_height 并不是固定值,它可以设置成 dpMATCH_PARENTWRAP_CONTENT 三种形式。

1.我们试想,如果用户设置了精确值 dp,那就好说,直接给 View 设置成精确的宽度,一旦用户给子 View 设置了 MATCH_PARENT(匹配父窗体),子 View 的宽度应该是父窗体的宽度,而问题是子 View 并不知道父窗体多宽。
2.为了解决这样的矛盾,Android 系统干脆规定:子 View 的宽高必须交给父 View 去测量。在测量时,父 View 会根据自己的尺寸和子 View 的LayoutParams,计算出一个 MeasureSpec(测量规则),也是父 View 对子 View 尺寸的期望。
3.然后遍历调用子 View 的measure(widthMeasureSpec,heightMeasureHeight)进行实际测量。测量完成,子 View 的宽高就确定了,可以通过 view.getMeasuredWidth()方法获取。整个过程如下图所示。

2.能简单说下测量的过程吗

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); 
4.测量规则是什么呢 widthMeasureSpec,heightMeasureSpec 我们知道他们是32位,32位中代表的含义
  1. widthMeasureSpecheightMeasureSpec是测量规则
  2. 是一个int 类型,但是它并不是实际的尺寸,而是尺寸和测量模式的合成值。
  3. 它在 int 类型的 32 位二进制位中,31-30 这两位表示模式,0~29 这三十位表示宽和高的实际值。
  4. 通过 MeasureSpec 类提供的静态方法,我们可以从 widthMeasureSpecheightMeasureSpec 中提取测量模式和期望尺寸。
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
5.如何确定的子类的测量模式

上面说了,父类测量子类是调用子 View 的 measure(widthMeasureSpec,heightMeasureHeight),这个两个测量 widthMeasureSpec 规则是父类根据自己的宽度和子类的 LayoutParams 计算出来的。
那么到底怎么计算测量规则,看下面一张图就全明白了(注意相同的颜色)。

Android 进阶面试相关笔录

Android 面试题锦:https://qr18.cn/CKV8OZ
Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值