您的位置:首页 > 其它

自定义View中为什么需要重写onMeasure()方法?

2014-10-30 15:54 417 查看
不实现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呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: