Android自定义控件之onMeasure详解

  在Android开发中往往需要根据需求对原生控件进行自定义,其中主要涉及到的就是onMeasure,onLayout和onDraw三个方法的重写与使用,其中onMeasure是其中最复杂的一个方法,很多程序员仅仅知道该方法用来测量大小,却不知道何时调用,如何去用,本文就对利用Linearlayout的源码来解析onMeasure.

 1.何时调用onMeasure

  onMeasure方法的作用时测量空间的大小,什么时候需要测量控件的大小呢?这个过程就同炒菜一样,在炒的时候你不需要考虑需要多少大小,只有你需要拿盘子装时,你才需要知道到底有多少菜,需要拿多大的盘子.             

    简单自定义Layout,和View并打出Log如下:

Android自定义控件之onMeasure详解_第1张图片
    由上图可以看出调用先后顺序是先调用父容器的onMeasure后调用View的onMeasure,实际上控件在创建时不需要知道大小,只需要先创建出在放入父容器时,父容器需要知道View大小时才去测量View的大小,接下来从源码来分析整个过程.

2.源码分析onMeasure调用

我们从LinearLayout的onMeasure为入口,开始分析整个过程:

Android自定义控件之onMeasure详解_第2张图片
    到这里先说明一下widthMeasureSpec和heightMeasureSpec这两个参数,两者实际是一样的,我们就用前者来说明,widthMeasureSpec用int值来表示,这个值由高32位和低16位组成,高32位保存的值叫specMode,可以通过如代码中所示的MeasureSpec.getMode()获取;低16位为specSize,同样可以由MeasureSpec.getSize()获取

    specMode组成与具体意义:

Android自定义控件之onMeasure详解_第3张图片
    这里就不过多解释,如果需要深入的同学请自行百度官方文档说明.
    接下来跟进看measureVertical方法,整个方法都在测量垂直方向的最终高度的值,该方法具体代码较长下面就展示关键代码:

Android自定义控件之onMeasure详解_第4张图片

      上面代码外面还有一个For循环包裹,循环次数是子View的数量,我们主要分析的事onMeasure的调用过程所以我们就不仔细解释代码,这里我们直接看measureChildBeforeLayout方法:
Android自定义控件之onMeasure详解_第5张图片 Android自定义控件之onMeasure详解_第6张图片
    最后实际调用的是getChildMeasureSpec方法获得View的宽和高的spec,最后调用View的measure方法,这里我们先看getChildMeasureSpec方法: Android自定义控件之onMeasure详解_第7张图片

Android自定义控件之onMeasure详解_第8张图片

    这个方法传入三个参数,分别是ViewGroup的spec,可利用的最大宽度/高度,和View的宽度/高度,以上就是通过ViewGroup的model,view的宽度/高度综合比较最后生成一个spc.view的宽度/高度的值主要分三种情况-1表示match_parent,-2表示wrap_content,和具体数值(需要大于等于0),具体过程总结为下表(盗用一下别人的表格):
Android自定义控件之onMeasure详解_第9张图片
     从这个表我们能看出来,当View没有具体大小时,其大小最后都与ViewGroup的大小一致,这也就解释了为什么自定义的View的wrap_content没有效果,View的大小不完全由其父View决定,还由自身的onMeasure方法决定.
    最终利用MeasureSpec. makeMeasureSpec(resultSize, resultMode)生成一个int的spc,最后调用View的measure方法,将子View的spc传进去,下面我们看measure方法:
Android自定义控件之onMeasure详解_第10张图片

    方法较长我们也不具体分析,看黄字部分,在这个方法最后调用了自身的onMeasure方法并将widthMeasureSpc传入,这也就是View中的onMeasure中两个参数的由来.
    以上就是在自定义View是onMeasure方法的具体调用过程,由于我们分析的是过程所以没有具体分析实现,希望对大家理解整个过程又一定的帮助,有错误也请及时指出.

 
  
 
  

你可能感兴趣的:(Android自定义控件之onMeasure详解)