Android中onMesure研究(1)

                                                                               

         当一个Activity取得焦点后就会向Android系统请求绘制它的布局。Android框架会处理这个绘制的过程,一个View的显示,需要先后调用onMeasure,onLayout和onDraw方法。从字面意思理解onMeasure,为计算,测量。上图所示,A,B,C分别表示为三个View,其中,A View包含B View,B View 又包含C View。这三个View在屏幕上显示出来, 会调用每一个View中的onMeasure方法,其调用的顺序是怎样的呢?A ----> B---->C 还是神马呢???先上代码吧。分别为A,B,C三个类源码码。                                                                                    

      

public class LayoutA extends LinearLayout{
	
	private String TAG = LayoutA.class.getSimpleName();
	
	public LayoutA(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public LayoutA(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int widthMode = MeasureSpec.getMode(widthMeasureSpec);
		int heightMode = MeasureSpec.getMode(heightMeasureSpec);
		
		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
		if(widthMode == MeasureSpec.AT_MOST){
			Log.e(TAG,"LayoutA onMeasure() called,widthMode = MeasureSpec.AT_MOST,widthSize = " + widthSize + " ,heightSize = " + heightSize);
		}
		
		if(widthMode == MeasureSpec.EXACTLY){
			Log.e(TAG,"LayoutA onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = " + widthSize + " ,heightSize = " + heightSize);
		}
		
		if(widthMode == MeasureSpec.UNSPECIFIED){
			Log.e(TAG,"LayoutA onMeasure() called,widthMode = MeasureSpec.UNSPECIFIED,widthSize = " + widthSize + " ,heightSize = " + heightSize);
		}
		
		if(heightMode == MeasureSpec.AT_MOST){
			
		}
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		// TODO Auto-generated method stub
		super.onLayout(changed, l, t, r, b);
//		Log.e(TAG,"  LayoutA  onLayout() called...");
	}


	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
//		Log.e(TAG,"  LayoutA  onDraw() called...");
	}

}

    ... ... ... ...

my_main.xml文件为:

<com.example.measuretest.LayoutA xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:background="#ffff0000">
     <com.example.measuretest.LayoutB
        android:layout_width="300dip"
        android:layout_height="300dip"
        android:gravity="center"
        android:layout_marginTop="40dip"
        android:background="#ff00ff00">
        <com.example.measuretest.LayoutC
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="@string/hello_world">
        </com.example.measuretest.LayoutC>
     </com.example.measuretest.LayoutB>
</com.example.measuretest.LayoutA>

类LayoutB与LayoutA相似,LayoutC的代码为:

public class LayoutC extends Button{
	
	private String TAG = LayoutC.class.getSimpleName();
	private float mRadius = 4;
	
	public LayoutC(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	public LayoutC(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
... ... ... ... ...


运行后,log信息为:

08-20 21:15:53.338: E/LayoutC(2377): LayoutC onMeasure() called,widthMode = MeasureSpec.AT_MOST,widthSize = 450 ,heightSize = 450
08-20 21:15:53.338: E/LayoutB(2377): LayoutB onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 450 ,heightSize = 450
08-20 21:15:53.338: E/LayoutA(2377): LayoutA onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 480 ,heightSize = 778
08-20 21:15:53.370: E/LayoutC(2377): LayoutC onMeasure() called,widthMode = MeasureSpec.AT_MOST,widthSize = 450 ,heightSize = 450
08-20 21:15:53.370: E/LayoutB(2377): LayoutB onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 450 ,heightSize = 450
08-20 21:15:53.370: E/LayoutA(2377): LayoutA onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 480 ,heightSize = 778
08-20 21:15:53.424: E/LayoutC(2377): LayoutC onMeasure() called,widthMode = MeasureSpec.AT_MOST,widthSize = 450 ,heightSize = 450
08-20 21:15:53.424: E/LayoutB(2377): LayoutB onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 450 ,heightSize = 450
08-20 21:15:53.424: E/LayoutA(2377): LayoutA onMeasure() called,widthMode = MeasureSpec.EXACTLY,widthSize = 480 ,heightSize = 778


从log信息显示为:先调用LayoutC 的onMeasure 方法,而后是LayoutB,最后才是调用LayoutA方法的onMeasure方法。

        绘制View有两个过程,一个messure过程和一个layout过程。  messure过程只通过measure(int, int)方法中实现的,messure过程会自顶向下遍历Viewtree。在递归过程中,每个View都设置自己的尺寸规格。在measure过程的最后,每个View都已经存储了它自身的大小了。

        由于是递归调用,所以当然是从最里层的view开始调用其onMeasure方法,计算其自身大小,然后调用次外层View 的onMeasure方法。也就是说,上图中A,B,C的调用顺序为:C------>B------->A

(关于measure的调用,请参看Google文档:http://developer.android.com/guide/topics/ui/how-android-draws.html


         


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值