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来实现,有时候在自定义控件的时候多数采用

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        setMeasuredDimension(widthSize, heightSize);

getDefaultSize代码如下:

    public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize =  MeasureSpec.getSize(measureSpec);        switch (specMode) {        case MeasureSpec.UNSPECIFIED:            result = size;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.EXACTLY:            result = specSize;            break;        }        return result;    }
3.onMeasure好像会调用两次,这点我没有到代码中具体跟踪了,如果该view的父view是RelativeLayout,则其父view的onMeasur也要测量一下。我在测试中用的xml为:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"  android:layout_width="match_parent"  android:layout_height="match_parent"><com.goso.ui.record.RecordViewandroid:id="@+id/uvMeter" android:layout_width="200dp"android:layout_height="80dp" android:layout_centerInParent="true" /></RelativeLayout><!-- RelativeLayout  LinearLayout-->

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stub    int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);    int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);    Log.e("HJJ", "****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );    int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(widthSize, heightSize);}

打印出的结果为:

01-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:71401-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:12001-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:71401-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:120

如果将RelativeLayout换成LinearLayout则为

01-06 12:51:17.980: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:12001-06 12:51:18.010: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:120





测试用的代码如下:

package com.goso.ui.record;import com.goso.ui.R;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.View;public class RecordView extends View{    static final float PIVOT_RADIUS = 3.5f;    static final float PIVOT_Y_OFFSET = 10f;    static final float SHADOW_OFFSET = 2.0f;    static final float DROPOFF_STEP = 0.18f;    static final float SURGE_STEP = 0.35f;    static final long  ANIMATION_INTERVAL = 70;        Paint mPaint, mShadow;public RecordView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubinit(context);}public RecordView(Context context) {super(context);// TODO Auto-generated constructor stubinit(context);}private void init(Context context){   Drawable bg = context.getResources().getDrawable(R.drawable.vumeter);   setBackgroundDrawable(bg);      mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);   mPaint.setColor(Color.WHITE);   mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);   mShadow.setColor(Color.argb(60, 0, 0, 0));}    private String getModeStr(int mode){    String modeStr = null;    switch (mode) {        case MeasureSpec.UNSPECIFIED:        modeStr = "UNSPECIFIED";            break;        case MeasureSpec.AT_MOST:        modeStr = "AT_MOST";        break;        case MeasureSpec.EXACTLY:        modeStr = "EXACTLY";            break;        }    return modeStr;    }    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stub//    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int specModeWidth = MeasureSpec.getMode(widthMeasureSpec);    int specSizeWidth = MeasureSpec.getSize(widthMeasureSpec);    int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);    int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);    //Log.e("HJJ", "specModeWidth:" + getModeStr(specModeWidth) + ", specSizeWidth:" + specSizeWidth );    Log.e("HJJ", "****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );//    Log.e("HJJ", "widthMeasureSpec:" + widthMeasureSpec + ", heightMeasureSpec:" + heightMeasureSpec );//    int widthSize = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);//int heightSize = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);    int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(widthSize, heightSize);//Log.e("HJJ", "width:" + widthSize + ", height:" + heightSize );}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);float w = getWidth();float h = getHeight();float pivotX = w / 2;float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;float l = h * 7 / 10;float angle = (float) Math.PI * 1/ 8;float sin = (float) Math.sin(angle);float cos = (float) Math.cos(angle);float x0 = pivotX - l * cos;float y0 = pivotY - l * sin;        canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);        canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);        canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);        canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);}}

<?xml version="1.0" encoding="utf-8"?><LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"  android:layout_width="match_parent"  android:layout_height="match_parent"><com.goso.ui.record.RecordViewandroid:id="@+id/uvMeter" android:layout_width="200dp"android:layout_height="80dp" android:layout_centerInParent="true" /></LinearLayout><!-- RelativeLayout  LinearLayout-->


更多相关文章

  1. android上一些方法的区别和用法的注意事项
  2. 安卓编程小tips
  3. Android(安卓)ImageView控件的MaxWidth、MaxHeight不起作用
  4. Android帧布局实现霓虹灯的效果
  5. android调用camera实现自定义照相
  6. Android(安卓)判断Intent是否存在
  7. Android(安卓)OpenGL学习笔记(二)之----三角形的绘制.
  8. Android-防止事件导致的oncreate的多次调用
  9. 【Android】报错:Can't create handler inside thread that has n

随机推荐

  1. 支持HTML5 SqlLite的AndroidApp
  2. 使用Fragment让程序界面一分为多
  3. Android(安卓)Drawable(Android开发艺术
  4. 4.0.x Launcher启动过程
  5. Android向桌面添加快捷方式,使其指向特定
  6. 一个常见Android崩溃问题的分析
  7. Android开发工具——ADB(Android(安卓)De
  8. 全面了解Activity
  9. 三、Pocketsphinx_Android中英文小范围高
  10. Android(安卓)ImageView手势缩放完整的实