不实现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呢?
时间: 2024-10-03 22:14:21