Android View 如何测量

  对于Android View的测量,咱们一句话总结为:"给我位置和大小,我就知道您长到那里"。android

  为了让你们更好的理解这个结论,我这里先讲一个平常生活中的小故事:不知道你们玩过"瞎子画画"的游戏没,一我的蒙上眼睛,拿笔去画板上画一些指定的图案,另一我的则充当他的"眼睛",经过语言告诉他在画板那个位置画一个多大的图案。假若,这我的不告诉那个蒙着眼睛的人,在那个画一个多大的图案。那么这个蒙着眼睛的人此时真是"河里赶大车----------没辙"。其实,Android就是这个蒙着眼睛的人,咱们必须精确地告诉他如何去画,它才能画出你所想要的图形。ide

  你们是否是对Android布局的测量进行现实世界进行类比了。为了实现View具体布局在哪儿,Android设计了一个短小精悍又功能强大的类——measureSpec类。这样妈妈不再用担忧我不会测量View了。那么,MeasureSpec究竟是个什么鬼了。MeasureSpec,归根结底是一个32位的int值。其中高2位表示测量的模式,低30位表示测量View的大小。这样作有什么好处。这样作经过位运算来提升运行效率。布局

  要了解MeasureSpec这个类的来弄去脉的话,务必要对测量的三种模式了解。设计

  1.EXACTLY(精准的)xml

  当您设置View的layout_height属性或layout_width属性为肯定的值或者为match_parent(填充父容器)时候,系统就将View测量模式设置为EXACTLY模式。blog

  2.AT_MOST(最大值)游戏

  即布局为最大值模式,那么何时系统会将View调整为AT_MOST模式了,即当您设置View的layout_height属性或layout_width属性为wrap_content(包裹内容)时候。get

  3.UNSPECIFIED(未肯定)it

  即没有肯定,没有指定大小测量模式,view即“心有多大,舞台就有多大"。这个方法,通常在自定义控件中才能用到。io

  View测量的时候,默认是EXACTLY模式,也许你会感到纳闷,TextView,EditText这些控件,他怎么就支持wrap_content属性了,难道他重写OnMeasure方法,是的,他们都重写OnMeasure方法。这就是为何咱们在自定义控件的时候,若是要布局支持wrap_content属性,就须要重写onMeasure方法,来指定wrap_content为确切的大小。

  这个关于测量模式的思惟导图应该是这样的:

  

  咱们知道这么多理论的知识,是否是以为即枯燥乏味又以为然并卵。好吧,咱们就直接上代码,在代码中解释MeasureSpec如何获取测量模式和测量的大小。源代码以下:

   Java代码以下:

public class MyView extends View {
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
}

  xml代码以下:

<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity" >
        
        <com.example.test.MyView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="#00ff00"
            />
</LinearLayout>

  运行效果以下所示:

  经过这个短小精悍的例子,充分证实这样一个结论:View测量的时候,默认是EXACTLY模式,你不重写OnMeasure方法,即便设置wrap_content属性,他也是填充父容器。

  那么,就经过MeasureSpec这个万金油类来重写一下OnMeasure方法。相应源代码以下:

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureWidth(heightMeasureSpec));
    }
    public int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = 200;
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(specSize, result);
            }
        }
        return result;
    }

  运行效果以下:

  一样的例子,咱们只不过是重写了OnMeasure方法,经过MeasureSpec.getMode(measureSpec)获取测量模式的时候,经过MeasureSpec.getSize(measureSpec)获取控件尺寸。判断当布局属性为wrap_content,指定为一确切值,这时,控件就符合wrap_content属性。

  本文对Android如何对控件进行测量介绍,本人才疏学浅,恳请你们指教。

相关文章
相关标签/搜索