转载请标明出处:一片枫叶的专栏
android中View在测量的过程中会回调方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
其中widthMeasureSpec和heightMeasureSpec是MeasureSpec类型的数据,我们可以通过它获取绘制模式和数值:
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
android体系的绘制模式有三种(自定义View的绘制模式默认为:EXACTLY):
AT_MOST,specSize 代表的是最大可获得的空间;
EXACTLY,specSize 代表的是精确的尺寸;
UNSPECIFIED,对于控件尺寸来说,没有任何参考意义,可以是任意大小,重要用于自定义。
当我们设置width或height为fill_parent时,容器在布局时调用子view的measure方法传入的模式是EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的。
而当设置为 wrap_content时,容器传进去的是AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸。
当子view的大小设置为精确值时,容器传入的是EXACTLY, 而MeasureSpec的UNSPECIFIED模式目前还没有发现在什么情况下使。
自定义View默认的测量模式是:EXACTLY,也就是说,如果自定义View不重写onMeasure方法的话,就只能使用EXACTLY,View只能相应fill_parent或者是具体值,若想view能够识别wrap_content,则需要我们重写onMeasure方法:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(heightMeasureSpec));
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
Log.i("tag", "specMode:" + specMode + " specSize:" + specSize + " " + MeasureSpec.UNSPECIFIED + " " + MeasureSpec.AT_MOST + " " + MeasureSpec.EXACTLY);
}
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
这样我们再次查看自定义View的显示效果:
- 当设置自定义View的宽高为:
<uuzuche.com.mhotfix.MView
android:id="@+id/mview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/holo_green_dark"
/>
- 当设置自定义View的宽高为:
<uuzuche.com.mhotfix.MView
android:id="@+id/mview"
android:layout_width="500dp"
android:layout_height="500dp"
android:background="@android:color/holo_green_dark"
/>
这里不太好展示,其实屏幕还没有完全沾满的,长宽分别是500dp
- 当设置自定义View的宽高为:
<uuzuche.com.mhotfix.MView
android:id="@+id/mview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_green_dark"
/>
这里完全占满屏幕。