理解onMeasure

61 篇文章 0 订阅
 

理解onMeasure

分类: Android   1227人阅读  评论(1)  收藏  举报

        Android系统调用onMeasure来定义view的大小,很长时间理解不是很透彻,今天花了些时间打日志来理解它。总结如下。

        1. widthMeasureSpec和heightMeasureSpec这两个值是android:layout_width="200dp" android:layout_height="80dp"来定义的,它由两部分构成,可通过int specModeHeight = MeasureSpec.getMode(heightMeasureSpec); int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec)来得到各自的值。

如果android:layout_width="wrap_content"或android:layout_width="fill_parent",哪么得到的specMode为MeasureSpec.AT_MOST,如果为精确的值则为MeasureSpec.EXACTLY。另外,specSize要想得到合适的值需要在Androidmanifest.xml中添加<uses-sdk android:minSdkVersion="10" />

        2.系统默认的onMeasure调用方法是getDefaultSize来实现,有时候在自定义控件的时候多数采用        

       

[java]  view plain copy
  1. int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  2. int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  3. setMeasuredDimension(widthSize, heightSize);  

            getDefaultSize代码如下:

           

[java]  view plain copy
  1. public static int getDefaultSize(int size, int measureSpec) {  
  2.     int result = size;  
  3.     int specMode = MeasureSpec.getMode(measureSpec);  
  4.     int specSize =  MeasureSpec.getSize(measureSpec);  
  5.   
  6.     switch (specMode) {  
  7.     case MeasureSpec.UNSPECIFIED:  
  8.         result = size;  
  9.         break;  
  10.     case MeasureSpec.AT_MOST:  
  11.     case MeasureSpec.EXACTLY:  
  12.         result = specSize;  
  13.         break;  
  14.     }  
  15.     return result;  
  16. }  
          3.onMeasure好像会调用两次,这点我没有到代码中具体跟踪了,如果该view的父view是RelativeLayout,则其父view的onMeasur也要测量一下。我在测试中用的xml为:

[java]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:orientation="vertical"  
  5.   android:layout_width="match_parent"  
  6.   android:layout_height="match_parent">  
  7.   
  8.     <com.goso.ui.record.RecordView  
  9.         android:id="@+id/uvMeter"   
  10.         android:layout_width="200dp"  
  11.         android:layout_height="80dp"   
  12.         android:layout_centerInParent="true" />  
  13. </RelativeLayout>  
  14. <!-- RelativeLayout  LinearLayout-->  

[java]  view plain copy
  1. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  2.     // TODO Auto-generated method stub  
  3.     int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);  
  4.     int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
  5.     Log.e("HJJ""****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );  
  6.   
  7.     int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  8.     int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  9.     setMeasuredDimension(widthSize, heightSize);  
  10. }  

打印出的结果为:

[html]  view plain copy
  1. 01-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:714  
  2. 01-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:120  
  3. 01-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:714  
  4. 01-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:120  

如果将RelativeLayout换成LinearLayout则为

[html]  view plain copy
  1. 01-06 12:51:17.980: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:120  
  2. 01-06 12:51:18.010: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:120  





测试用的代码如下:

[java]  view plain copy
  1. package com.goso.ui.record;  
  2.   
  3. import com.goso.ui.R;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.Color;  
  8. import android.graphics.Paint;  
  9. import android.graphics.drawable.Drawable;  
  10. import android.util.AttributeSet;  
  11. import android.util.Log;  
  12. import android.view.View;  
  13.   
  14. public class RecordView extends View{  
  15.     static final float PIVOT_RADIUS = 3.5f;  
  16.     static final float PIVOT_Y_OFFSET = 10f;  
  17.     static final float SHADOW_OFFSET = 2.0f;  
  18.     static final float DROPOFF_STEP = 0.18f;  
  19.     static final float SURGE_STEP = 0.35f;  
  20.     static final long  ANIMATION_INTERVAL = 70;  
  21.       
  22.     Paint mPaint, mShadow;  
  23.     public RecordView(Context context, AttributeSet attrs) {  
  24.         super(context, attrs);  
  25.         // TODO Auto-generated constructor stub  
  26.         init(context);  
  27.     }  
  28.   
  29.     public RecordView(Context context) {  
  30.         super(context);  
  31.         // TODO Auto-generated constructor stub  
  32.         init(context);  
  33.     }  
  34.   
  35.     private void init(Context context){  
  36.        Drawable bg = context.getResources().getDrawable(R.drawable.vumeter);  
  37.        setBackgroundDrawable(bg);  
  38.          
  39.        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
  40.        mPaint.setColor(Color.WHITE);  
  41.        mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);  
  42.        mShadow.setColor(Color.argb(60000));  
  43.     }  
  44.       
  45.     private String getModeStr(int mode){  
  46.         String modeStr = null;  
  47.         switch (mode) {  
  48.         case MeasureSpec.UNSPECIFIED:  
  49.             modeStr = "UNSPECIFIED";  
  50.             break;  
  51.         case MeasureSpec.AT_MOST:  
  52.             modeStr = "AT_MOST";  
  53.             break;  
  54.         case MeasureSpec.EXACTLY:  
  55.             modeStr = "EXACTLY";  
  56.             break;  
  57.         }  
  58.         return modeStr;  
  59.     }  
  60.       
  61.     @Override  
  62.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  63.         // TODO Auto-generated method stub  
  64. //      super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  65.         int specModeWidth = MeasureSpec.getMode(widthMeasureSpec);  
  66.         int specSizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
  67.         int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);  
  68.         int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
  69.         //Log.e("HJJ", "specModeWidth:" + getModeStr(specModeWidth) + ", specSizeWidth:" + specSizeWidth );  
  70.         Log.e("HJJ""****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );  
  71. //      Log.e("HJJ", "widthMeasureSpec:" + widthMeasureSpec + ", heightMeasureSpec:" + heightMeasureSpec );  
  72. //      int widthSize = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);  
  73. //      int heightSize = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);  
  74.           
  75.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
  76.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
  77.         setMeasuredDimension(widthSize, heightSize);  
  78. //      Log.e("HJJ", "width:" + widthSize + ", height:" + heightSize );  
  79.     }  
  80.       
  81.     @Override  
  82.     protected void onDraw(Canvas canvas) {  
  83.         // TODO Auto-generated method stub  
  84.         super.onDraw(canvas);  
  85.           
  86.         float w = getWidth();  
  87.         float h = getHeight();  
  88.         float pivotX = w / 2;  
  89.         float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;  
  90.           
  91.         float l = h * 7 / 10;  
  92.         float angle = (float) Math.PI * 18;  
  93.           
  94.         float sin = (float) Math.sin(angle);  
  95.         float cos = (float) Math.cos(angle);  
  96.           
  97.         float x0 = pivotX - l * cos;  
  98.         float y0 = pivotY - l * sin;  
  99.           
  100.         canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);  
  101.         canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);  
  102.         canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);  
  103.         canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);  
  104.           
  105.           
  106.     }  
  107. }  

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  
  3.   xmlns:android="http://schemas.android.com/apk/res/android"  
  4.   android:orientation="vertical"  
  5.   android:layout_width="match_parent"  
  6.   android:layout_height="match_parent">  
  7.   
  8.     <com.goso.ui.record.RecordView  
  9.         android:id="@+id/uvMeter"   
  10.         android:layout_width="200dp"  
  11.         android:layout_height="80dp"   
  12.         android:layout_centerInParent="true" />  
  13. </LinearLayout>  
  14. <!-- RelativeLayout  LinearLayout-->  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值