自定义控件---测量(ViewGroup测量)

时间:2024-03-19 08:29:49

自定义控件---测量(ViewGroup测量)

1 : 

1:父View会遍历测量每一个子View(通常使用ViewGroup类的measureChildWithMargins方法),然后调用子View的measure方法并且将测量后的宽高作为measure方法的参数,但是这只是父View的建议值,子View可以通过继承onMeasure来改变测量值。

(在上一篇文章已经有伪代码实现)

2:ViewGroup类型的View自身的测量是在ViewGroup类型的View的onMeasure方法中进行测量的(比如LinearLayout)

    它实现了这么几个功能 :

2.1 遍历子控件的尺寸并累积加上margin尺寸,分割线等并作为成员变量保存(measureChildWithMargins() 函数的 totalLength变量) 

2.2  完成子控件测量之后,通过 将父控件自身测量的尺寸保留起来。

   setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), heightSizeAndState);

2.2.1 :resolveSizeAndState() 函数 作用:修正父控件测量侧尺寸,当 父控件是配置的是 wrap_content 时,

           它的高度不能超出 剩余的空间 。

2.2.2 : measureChildWithMargins() 函数需要调用 getChildMeasureSpec() 函数返回的子元素MeasureSpec与父容器的MeasureSpec、父容器的padding、子元素的margin和兄弟元素占用的长度有关

     final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, mPaddingLeft + mPaddingRight +          lp.leftMargin + lp.rightMargin, lp.width);

child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

    getChildMeasureSpec() 函数实现可以抽象为下面的关系自定义控件---测量(ViewGroup测量)

3:所以,如果你自定义控件继承ViewGroup 就必须实现onMeasure()函数,否则会有异常(是不是以前碰到过 )

     当配置的是 wrap_content时,需要注意给一个尺寸我。否则就相当于配置match_parent (上篇文章已经解释了)

 

源码实现+ 伪代码实现 :

自定义控件---测量(ViewGroup测量)

自定义控件---测量(ViewGroup测量)


自定义控件---测量(ViewGroup测量)

5: 下面介绍下 :MeasureSpec (伪代码实现)

    MeasureSpec 其实就是尺寸和模式通过各种位运算计算出的一个整型值,它提供了三种模式,还有三个方法(合成约束、分离模式、分离尺寸)-----后面再补充自己个人理解

自定义控件---测量(ViewGroup测量)

总结  : 

  1:测量控件大小是父控件发起的,View控件直接通过onMeasue来测量自己,ViewGroup控件,没有onMeasue(),需要重写onMeasue函数,并做一系列操作,回调至View测量流程
  2:父控件要测量子控件大小,需要重写onMeasure()方法,然后调用measureChildWithMargin(),并且需要通过   getChildMeasureSpec()函数获取子控件的 测量策略,最后设置给onMeasure()方法中
  onMeasure()方法的参数是通过getChildMeasureSpec生成的
3 :如果我们自定义控件需要使用wrap_content,我们需要重写onMeasure()方法,并且注意要自己设置一个尺寸值
4:测量控件的步骤:
父控件onMeasure----->  measureChildWithMargin---->  getChildMeasureSpec----> 子控件的measure----->  onMeasure----> setMeasureDimension-----> 父控件测量子控件onMeasure结束调用-----》setMeasureDimension`保存自己的大小