measure机制流程理解

初始入门,没有看具体的源码,只是用到时结合几篇文章得出自己目前的理解。有很多错误的地方,以后在学习研究内核剖析时在深入研究


参考:


(1)最外层根视图得到MeasureSpec的流程

对于每一个View,包括DecorView,都持有一个MeasureSpec,而该MeasureSpec则保存了该View的尺寸规格。那么,对于DecorView来说,它已经是顶层view了,没有父容器,那么它的MeasureSpec怎么来的呢?

步骤:

  1. View系统的绘制流程会从ViewRoot的performTraversals()方法中开始
    ——>

  2. 调用getRootMeasureSpec(int windowSize, int rootDimension)方法去获取widthMeasureSpec和heightMeasureSpec的值(是根视图的MeasureSpec,详细实现于3),用于传递给measure()的参数

    • windowSize→赋值:desiredWindowWidth或desiredWindowHeight。是屏幕的尺寸,相当于specSize都是等于windowSize
    • rootDimension→赋值:lp.width或lp.height,相当于MATCH_PARENT(根视图全屏)

    ——>

  3. getRootMeasureSpec()里使用MeasureSpec.makeMeasureSpec()方法来组装一个MeasureSpec。具体分类:

    • rootDimension:MATCH_PARENT→MeasureSpec的specMode:EXACTLY
    • rootDimension:WRAP_CONTENT→MeasureSpec的specMode:AT_MOST
    • 并且MATCH_PARENT和WRAP_CONTENT时的specSize都是等于windowSize的

    ——>

    以上就是得到了一份DecorView根视图的MeasureSpec:childWidthMeasureSpec和childHeightMeasureSpec

  4. 接着就执行performMeasure里的 performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec)方法,调用其中的mView.measure(mView就是DecorView)也就是说,从顶级View开始了测量流程,那么我们直接进入measure流程。

注:由于DecorView继承自FrameLayout,是PhoneWindow的一个内部类,而FrameLayout没有measure方法,因此调用的是父类View的measure方法。
我们知道,整棵View树的根节点是DecorView,它是一个FrameLayout,所以它是一个ViewGroup,所以整棵View树的测量是从一个ViewGroup对象的measure方法开始的。
(有疑问)


measure流程可以分为两类:

  • ViewGroup的测量流程
  • View的测量流程

我们先看View类中measure和onMeasure函数:

(2)View的测量流程

  1. view类中的measure()方法,无法在子类中去重写这个方法
    public final void measure(int widthMeasureSpec, int heightMeasureSpec);
    ——>

  2. onMeasure()方法回调,才是真正去测量并设置View大小的地方。可以默认实现,也可以自定义实现

    • 2.1. onMeasure的默认实现很简单,源码如下:
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
            getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }
    /*
    onMeasure()默认会调用getDefaultSize(int size, int measureSpec)方法来获取视图的大小
    1、系统默认行为
    2、MeasureSpec.UNSPECIFIED时,返回size(理解:具体布局数值,则measure()没有必要了)
    3、specMode等于AT_MOST或EXACTLY时,就返回specSize(specSize = MeasureSpec.getSize(measureSpec))
    */
    • 2.2.当然也可以重载onMeasure,并调用setMeasuredDimension来设置任意大小的布局,但一般不这么做,因为这种做法太“专政”。

3.之后会在onMeasure()方法中调用setMeasuredDimension()方法来设定测量出的大小,即把测量结果保存起来,具体保存在mMeasuredWidth和mMeasuredHeight中。结束一次measure过程。//


(3)ViewGroup的测量流程

  1. ViewGroup中定义了一个measureChildren()方法来去测量(遍历所有)子视图的大小
    protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec);

    ——>

  2. 逐个调用measureChild()方法来测量相应子视图的大小。 protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec)
    protected void measureChildWithMargins(View child,
    int parentWidthMeasureSpec, int widthUsed,
    int parentHeightMeasureSpec, int heightUsed)

    对于ViewGroup的子类而言(非ViewGroup的View而言,通过调用上面默认的measure——>onMeasure,即可完成View的测量),以上一次遍历就是对父视图提供的measureSpec参数进行了调整(结合自身的LayoutParams参数),具体通过函数getChildMeasureSpec来进行参数调整,然后再来调用child.measure()函数。
    ——>

  3. measureChildren过程中最困难的一部分,为child计算MeasureSpec。该方法为每个child的每个维度(宽、高)计算正确的MeasureSpec。目标就是把当前viewgroup的MeasureSpec和child的LayoutParams结合起来,生成最合理的结果。
    public static int getChildMeasureSpec(int spec, int padding, int childDimension)
    具体实现:通过父视图的measureSpec、自身的lp参数(layout_width和layout_height中定义的,childDimension包括:具体数值、LayoutParams.MATCH_PARENT、LayoutParams.WRAP_CONTENT)和size(自身大小 int size = Math.max(0, specSize - padding); )来计算自身的measureSpec
    ——>
  4. 接着循环到4,直到遍历完所有子视图。测量始于DecorView,通过不断的遍历子View的measure方法,根据ViewGroup的MeasureSpec及子View的LayoutParams来决定子View的MeasureSpec,进一步获取子View的测量宽高,然后逐层返回,不断保存ViewGroup的测量宽高。

  • 总之:视图大小的控制是由父视图、布局文件、以及视图本身共同完成的,父视图会提供给子视图参考的大小,而开发人员可以在XML文件中指定视图的大小,然后视图本身会对最终的大小进行拍板。
  • 探究:EXACTLY、AT_MOST与MATCH_PARENT和WRAP_CONTENT的关系??
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值