View体系(八)深入剖析View的onMeasure方法
之前的文章《View体系(六)View工作流程入口》介绍了View
是从什么地方开始它的工作流程的,《View体系(七)理解 MeasureSpec》介绍了View
在measure
流程时的一个重要参数。有了上两篇的铺垫,我们就来看一下View
的onMeasure
方法到底做了什么。
(注:文中源码基于
Android 12
)
在View
做测量时,会调用View
的onMeasure
方法:
1 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
这里只调用了一个setMeasuredDimension
方法,看它的注释:
This method must be called by {@link #onMeasure(int, int)} to store the measured width and measured height.
可以知道,这个方法是用来存储测量的宽度和测量的高度的。
继续看setMeasuredDimension
方法里面调用了getDefaultSize
,该方法用于获取View
默认的大小:
1 | public static int getDefaultSize(int size, int measureSpec) { |
specMode
和specSize
之前的文章中讲过,表示测量模式和测量大小。这段代码表示根据不同的specMode
来返回不同的result
值,即View
测量的大小。可以看到注释①
处不管是AT_MOST
还是EXACTLY
,都返回specSize
,也就是说,对于一个直接继承自View
的自定义View
来说,它的wrap_content
和match_parent
属性的效果是一样的。因此我们自定义View
时,如果要使wrap_content
属性生效,就必须重写onMeasure
方法并根据specMode
来返回指定的大小。
现在我们知道了specSize
是测量的大小,那传入的第一个参数size
又是个什么?我们看传入的getSuggestedMinimumWidth
方法做了什么:
1 | protected int getSuggestedMinimumWidth() { |
这里先判断View
是否有背景,如果有,就返回背景宽度和View
最小宽度中较大的一个;如果没有,就直接返回View
的最小宽度,即mMinWidth
。默认的mMinWidth
为0,对应xml
文件中的android:minWidth
属性。
至此,View
的onMeasure
方法我们就分析完了,其做的工作很简单,就是保存View
的测量尺寸。在我们自定义View
时,我们根据自己的需求来重写onMeasure
方法,并对View
的尺寸自己进行测量并调用setMeasuredDimension
方法进行保存。
关注我