不实现OnMeasure()方法的时候
首先自定义一个简单的view:
public class myView extends View
{
public myView(Context context) {
super(context);
}
public myView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
在布局中使用:<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"
>
<com.example.callbacktest.myView
android:background="@android:color/black"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
/>
</RelativeLayout>
显示为:
如果layout_width和layout_height都改成wrap_content,显示的内容还是一样的全屏。
所以可以得出结论在不重写onMeasure()方法的时候默认自定义VIew是填充满父控件的。
如果需要使用wrap_content属性(根据内容确定控件大小),必须重写该方法。
在特定的模式下执行相应的操作。
onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法的作用主要
是告诉父控件自己需要多少空间,主要的方法是setMeasuredDimension(width, height)
用于保存控件的大小,如果不调用将会报出异常。
重写后的自定义view:
package com.example.callbacktest;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
public class myView extends View
{
private static final int DEFUALT_WIDTH = 200;
private static final int DEFUALT_HEIGHT = 100;
public myView(Context context) {
super(context);
}
public myView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = measureDemission(DEFUALT_WIDTH,widthMeasureSpec);
int height = measureDemission(DEFUALT_HEIGHT,heightMeasureSpec);
setMeasuredDimension(width, height);
}
private int measureDemission(int defualtSize,int measureSpec) {
int result = defualtSize;
int mode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
//EXACTLY:使用母控件给出的确切的尺寸(specSize),
//确定的大小一般是由控件写好的:layout_widht = "50dp",layout_height = "50dp"
//或者使用的fill_parent,这两种情况都可以确定大小。
if(mode == MeasureSpec.EXACTLY)
{
result = specSize;
}
//AT_MOST:不能超过母控件所给出的尺寸(specSize)
//一般用于不能确定的小的时候,如wrap_content。
else if(mode == MeasureSpec.AT_MOST)
{
result = Math.min(result,specSize);
}
//UNSPECIFIED:表示显示的控件大小没有指定。
else if(mode == MeasureSpec.UNSPECIFIED)
{
result = defualtSize;
}
return result;
}
}
详细请看注释,由于此自定义控件没有内容,所以此处给出了默认值的大小DEFUALT_WIDTH,和DEFUALT_HEIGHT.。
在AT_MOST模式下一般你可以根据自定义控件内容的size来代替。
这里还是对int类型的widthMeasureSpec和heightMeasureSpec不是很了解,怎么就能根据一个int类型获得mode和size呢?