在我们自定义View的时候,在默认情况下,也就是继承View之后,不进行什么处理的时候,我们设置这个自定义View的宽高都为wrap_content。
class WrapContentView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="MissingDefaultResource">
<wrapcontentview.WrapContentView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#2979FF" />
</LinearLayout>
就这样,我们运行效果最终View填充了父View,也就是和match_parengt的效果一样,下面我们来分析下原因。 首先我们需要知道在默认情况下,View是怎么设置这个大小的。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
其中setMeasureDimension是设置View宽高的,getDefaultSize是个关键方法,我们接下来看下这个它的源码:
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
从这显然可以看出来了,当specMode为AT_MOST和EXACTLY时候,它们走的是同一段代码result=specSize;这也就是wrap_content和match_parent是一个效果的原因。