从图到源码,你一定能读懂View的Measure方法
2023-12-05 19:56:35
前言
本篇是《读懂View》系列的第二篇文章,在上一篇文章中,我们介绍了View的绘制流程,了解了View的绘制过程主要分为三个步骤:measure、layout和draw。
本篇文章将正式开始讲解View的这三大绘制方法,本篇将讲述第一个方法—— Measure 方法。
Measure方法
Measure方法是View绘制的第一步,它的作用是确定View的大小,也就是确定View在屏幕上所占用的空间。
Measure方法的原型如下:
protected void measure(int widthMeasureSpec, int heightMeasureSpec)
其中,widthMeasureSpec和heightMeasureSpec是两个整型参数,它们表示了父View对当前View的测量约束条件。
这两个参数的具体格式如下:
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, mode);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, mode);
其中,width和height是父View希望子View的大小,mode是测量模式,它可以是以下三种之一:
- EXACTLY:父View希望子View的大小为width和height。
- AT_MOST:父View希望子View的大小不超过width和height。
- UNSPECIFIED:父View对子View的大小没有任何限制。
Measure方法的实现
Measure方法的实现比较复杂,这里我们只简单介绍一下它的基本原理。
Measure方法首先会调用子View的onMeasure方法,子View的onMeasure方法会根据父View的测量约束条件来计算自己的大小,然后将计算结果返回给父View。
父View拿到子View的大小后,会根据自己的测量约束条件来计算自己的大小,然后将计算结果返回给自己的父View。
以此类推,直到根View计算出自己的大小,整个Measure过程就结束了。
测量模式
在Measure方法中,测量模式是一个非常重要的概念。
测量模式有三种:EXACTLY、AT_MOST和UNSPECIFIED。
- EXACTLY:父View希望子View的大小为width和height。
- AT_MOST:父View希望子View的大小不超过width和height。
- UNSPECIFIED:父View对子View的大小没有任何限制。
不同的测量模式,子View的计算方式是不同的。
- EXACTLY模式 :子View的大小必须为width和height。
- AT_MOST模式 :子View的大小不能超过width和height,但可以小于width和height。
- UNSPECIFIED模式 :子View的大小可以是任意值。
源码案例分析
为了更好地理解Measure方法的工作原理,我们来看一个具体的源码案例。
public class MyView extends View {
private int mWidth;
private int mHeight;
public MyView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 获取父View的测量约束条件
int parentWidthMeasureSpec = MeasureSpec.getMode(widthMeasureSpec);
int parentHeightMeasureSpec = MeasureSpec.getMode(heightMeasureSpec);
// 获取父View希望的子View的大小
int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
// 根据父View的测量约束条件来计算自己的大小
int width;
int height;
if (parentWidthMeasureSpec == MeasureSpec.EXACTLY) {
width = parentWidth;
} else {
width = mWidth;
}
if (parentHeightMeasureSpec == MeasureSpec.EXACTLY) {
height = parentHeight;
} else {
height = mHeight;
}
// 设置自己的大小
setMeasuredDimension(width, height);
}
}
在这个例子中,MyView的onMeasure方法首先获取了父View的测量约束条件,然后根据父View的测量约束条件来计算自己的大小。
如果父View的测量约束条件是EXACTLY,那么MyView的大小就必须为父View希望的大小。
如果父View的测量约束条件是AT_MOST,那么MyView的大小就不能超过父View希望的大小,但可以小于父View希望的大小。
如果父View的测量约束条件是UNSPECIFIED,那么MyView的大小可以是任意值。
总结
Measure方法是View绘制的第一步,它的作用是确定View的大小。
Measure方法的实现比较复杂,但基本原理并不难理解。
在Measure方法中,测量模式是一个非常重要的概念。
不同的测量模式,子View的计算方式是不同的。
希望本文能帮助您理解View的Measure方法。