Rumah > Soal Jawab > teks badan
下面是我的测试程序, 重写了 View 中的 getDefaultSize 方法,打印出每次调用 getDefaultSize 的时候传递进来的 measureSpec 的模式,在主 activity 的 xml 中放了 3 个 TestView,分别使用 wrap_content、match_parent、具体 dp 值,来指定 layout_width 和 layout_height 的值,期望通过 log 看到 3 个 view 在调用自己的 onMeasure 方法的时候传递进来的测量约束的模式。但是打印结果让我很糊涂,因为打印的结果和设置的值看起来并不是一一对应的关系?所以我想问,测量模式和 layout_width 的值的类型是到底什么对应关系?
MainActivity 布局文件如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.testmeasurespec.MainActivity" >
<com.example.testmeasurespec.TestView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_launcher"
android:tag="test1" />
<com.example.testmeasurespec.TestView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/ic_launcher"
android:tag="test2" />
<com.example.testmeasurespec.TestView
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/ic_launcher"
android:tag="test3" />
</RelativeLayout>
测试 TestView 类如下:
public class TestView extends View {
private static final String TAG = "TestView";
public TestView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TestView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TestView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
Log.i(TAG, "onMeasure:" + getTag());
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
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:
Log.i(TAG, "specMode:MeasureSpec.UNSPECIFIED");
result = size;
break;
case MeasureSpec.AT_MOST:
Log.i(TAG, "specMode:MeasureSpec.AT_MOST");
case MeasureSpec.EXACTLY:
Log.i(TAG, "specMode:MeasureSpec.EXACTLY");
result = specSize;
break;
}
return result;
}
}
打印结果如下:
11-21 16:13:48.812: I/TestView(21213): onMeasure:test3
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): onMeasure:test2
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): onMeasure:test1
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): onMeasure:test3
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): onMeasure:test2
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): onMeasure:test1
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.812: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.892: I/TestView(21213): onMeasure:test3
11-21 16:13:48.892: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.892: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.892: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.892: I/TestView(21213): onMeasure:test2
11-21 16:13:48.892: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.892: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): onMeasure:test1
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): onMeasure:test3
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): onMeasure:test2
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): onMeasure:test1
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.AT_MOST
11-21 16:13:48.902: I/TestView(21213): specMode:MeasureSpec.EXACTLY
迷茫2017-04-17 12:06:07
最简单的映射关系是:
* wrap_parent -> MeasureSpec.AT_MOST
* match_parent -> MeasureSpec.EXACTLY
* 具体值 -> MeasureSpec.EXACTLY
但是上面代码由于放在 RelativeLayout 中,RelativeLayout 是一个比较复杂的 ViewGroup,其中子 view 的大小不仅跟 layout_width、layout_height 属性相关,还更很多属性有关系,所以会改变上述映射情况,使结果变得特别复杂。