• 普通View的measure流程


    对于普通的view,其测量在ViewGroup中的measureChildWithMargins函数中调用child view的measure开始测量。

    1:从measure函数开始

     1     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
     2         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
     3                 widthMeasureSpec != mOldWidthMeasureSpec ||
     4                 heightMeasureSpec != mOldHeightMeasureSpec) {
     5 
     6             // first clears the measured dimension flag
     7             mPrivateFlags &= ~MEASURED_DIMENSION_SET;
     8 
     9             if (ViewDebug.TRACE_HIERARCHY) {
    10                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
    11             }
    12 
    13             // measure ourselves, this should set the measured dimension flag back
    14             onMeasure(widthMeasureSpec, heightMeasureSpec);
    15 
    16             // flag not set, setMeasuredDimension() was not invoked, we raise
    17             // an exception to warn the developer
    18             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
    19                 throw new IllegalStateException("onMeasure() did not set the"
    20                         + " measured dimension by calling"
    21                         + " setMeasuredDimension()");
    22             }
    23 
    24             mPrivateFlags |= LAYOUT_REQUIRED;
    25         }
    26 
    27         mOldWidthMeasureSpec = widthMeasureSpec;
    28         mOldHeightMeasureSpec = heightMeasureSpec;
    29     }

    官方关于此函数的说明:measure函数用来计算一个view的尺寸,其传入的参数为parentView对此view的宽/高限制信息。实际的尺寸测量将会调用onMeasure来完成,因此,子类必须重写onMeasure函数。

    通过measure函数的源码我们也可以知道:首先,它是final的,所以不可以重写;其次,它主要是对传入的parentView的宽高限制信息进行了是否与上一次的相同的判断,若是相同则不调用onMeasure重新测量;

    2:measure ——> onMeasure函数

    1     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    2         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
    3                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    4     }

    通过其代码,我们可以知道主要用了这三个函数,我们一一分析:

    2.1:getSuggestedMinimumWidth函数:返回android:minWidth和背景宽度二者之间的最大值

     1 protected int getSuggestedMinimumWidth() {
     2     int suggestedMinWidth = mMinWidth; //mMinWidth对应android:minWidth属性所指定的值,如果它没有指定,那么默认为0
     3 
     4     if (mBGDrawable != null) {   //如果设置了背景
     5         final int bgMinWidth = mBGDrawable.getMinimumWidth(); //背景的宽度,如果是ShapeDrawable那么为0,如果是BitmapDrawable则有原始宽高
     6         if (suggestedMinWidth < bgMinWidth) {  //如果设定的最小值小于背景图片宽度,那么设定最小值为背景图片宽度 
     7             suggestedMinWidth = bgMinWidth;
     8         }
     9     }
    10 
    11     return suggestedMinWidth;
    12 }

    2.2:getDefaultSize:如果measureSpec没有限定则返回size,否则返回measureSpec中的size

     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     }

    到此:我们可以总结getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec)的逻辑:如果parentView对尺寸没有限制(即parentView的模式为UNSPECIFIED),那么将返回view的suggested最小值,否则返回parentView指定的尺寸。getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec)类似。

    2.3 setMeasuredDimension:很简单,设置测量的宽高(注意不是view实际的宽高,实际的宽高要等layout完成之后才确定,虽然几乎全部就是measure后的宽高)

    1     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
    2         mMeasuredWidth = measuredWidth;
    3         mMeasuredHeight = measuredHeight;
    4 
    5         mPrivateFlags |= MEASURED_DIMENSION_SET;
    6     }

    至此,关于onMeasure函数分析结束。

    ===================================================================

    http://www.cnblogs.com/willhua/

    ===================================================================

  • 相关阅读:
    20155313 2016-2017-2《Java程序设计》课程总结
    java第四次实验
    java第五次实验
    20155313 实验三《Java面向对象程序设计》实验报告
    20155313 2016-2017-2 《Java程序设计》第十周学习总结
    20155311《Java程序设计》实验五(网络编程与安全)实验报告
    学号20155311 2016-2017-2《Java程序设计》课程总结
    20155311高梓云补交的Mypc课下实践
    20155311 《Java程序设计》实验四 (Android程序设计)实验报告
    20155311 实验三 敏捷开发与XP实践 实验报告
  • 原文地址:https://www.cnblogs.com/willhua/p/5612880.html
Copyright © 2020-2023  润新知