一、View大小测量
子控件的大小是由父控件和子控件共同决定的,子控件模式的有三种,EXACTLY(对应match_parent,或某个常量),AT_MOST(对应wrap_content),UNSPECIFIED(不常用)。在EXACTLY模式中,父控件将分配子控件固定大小,不管子控件真实大小是多少;在AT_MOST模式中,子控件大小由自己决定,但最多不能超过某个特定Size,在子控件onMeasure()方法中进行;在UNSPECIFIED模式中,父控件不理会子控件大小,完全由子控件自己决定。
总而言之,子控件大小由两个因素决定,子控件宽高(Width/Height)以及模式(Mode),在View中定义了MeasureSpec内部类,将控件的大小Size与Mode通过移位操作合并成一个int类型以节省内存。
1、MeasureSpec内部类API描述
MeasureSpec的值由specSize和specMode共同组成的,其中specSize记录的是大小,specMode记录的是规格。
public static class MeasureSpec {
//三种测量模式,对应match_parent或某个常量,wrap_content
public static final int UNSPECIFIED = 0
public static final int EXACTLY = 1
public static final int AT_MOST = 2
//根据给定的Size和Mode,通过移位获得混合int值
public static int makeMeasureSpec(int size, int mode)
//从给定的measureSpec中,提取mode信息
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
//从给定的measureSpec中获得Size信息
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
//获得mode和size
public static String toString(int measureSpec)
}
2、Measure()的API描述
调用Measure()测量控件的大小,由其父控件提供结构信息(宽高)。真正的测量工作在onMeasure()方法中进行,onMeasure()由Measure()方法调用。因此,只需要重写onMeasure()方法即可。
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
...
onMeasure(widthMeasureSpec, heightMeasureSpec);
...
}
3、onMeasure()的API描述
调用该方法测量View的真实大小,这个方法是由measure()方法调用,在自定义控件中,onMeasure()需要被覆盖,如未被覆盖,控件的EXACTLY模式能够被真实测量,但Wrap_content模式,还将返回父控件允许的最大值,即还是mat