重新复习 MeasureSpec在View测量中的作用

我留下了比较重要的三个方法:

  • makeMeasureSpec。用于生成一个MeasureSpec,生成的方式就是size+mode,得到一个32位的int值。
  • 获取mode。也就是取前2位的值作为mode。
  • 获取size。也就是取后30位的值作为size。

至此,我们至少知道了MeasureSpec是一个32位的int值,高2位为mode(测量模式),低30位为size(测量大小)。

这么做的目的主要是避免过多的对象内存分配。

所以我们可以大致猜测,这个MeasureSpec就是用来标记View的测量参数,其中测量模式可能和View具体怎么显示有关,而测量大小就是值的View实际大小。

当然,这只是我们的初步猜测。

要搞清楚具体信息,就要从View树的绘制测量开始说起。

DecorView的测量

上文说到,测量代码是从ViewRootImpl的measureHierarchy开始的,然后会执行到performMeasure方法:


  1. private void measureHierarchy(){ 
  2.  childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width); 
  3.        childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); 
  4.        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); 
  5.  
  6.  
  7.    private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { 
  8.        try { 
  9.            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec); 
  10.        } finally { 
  11.            Trace.traceEnd(Trace.TRACE_TAG_VIEW); 
  12.        } 
  13.    } 

很明显,在这里就会进行第一次MeasureSpec的计算,并且传给了下层的mView,也就是DecorView。

那我们就来看看DecorView的MeasureSpec测量规格计算方式:


  1. private static int getRootMeasureSpec(int windowSize, int rootDimension) { 
  2.        int measureSpec; 
  3.        switch (rootDimension) { 
  4.  
  5.        case ViewGroup.LayoutParams.MATCH_PARENT: 
  6.            // Window can't resize. Force root view to be windowSize. 
  7.            measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY); 
  8.            break; 
  9.        case ViewGroup.LayoutParams.WRAP_CONTENT: 
  10.            // Window can resize. Set max size for root view
  11.            measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST); 
  12.            break; 
  13.        default
  14.            // Window wants to be an exact sizeForce root view to be that size
  15.            measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY); 
  16.            break; 
  17.        } 
  18.        return measureSpec; 
  19.    } 

所以DecorView是和它的LayoutParams有关,其实也就是跟Window的调整有关,如果Window是子窗口,那么就可以调整,比如Dialog的宽高设置为WRAP_CONTENT,那么DecorView对应的测量规格就是AT_MOST。

到此,我们也可以初步得到这个测量规格mode的含义:

  • 如果View的值是确定大小,比如MATCH_PARENT或者固定值,那么它的测量模式就是MeasureSpec.EXACTLY。
  • 如果View的值是自适应,比如WRAP_CONTENT,那么它的测量模式就是 MeasureSpec.AT_MOST。

具体是不是这样呢?我们继续到下层View一探究竟。

View/ViewGroup的测量

对于具体的View/ViewGroup 测量,就涉及到另外的一个方法measureChildWithMargins,这个方法也是在很多布局中会看到,比如LinearLayout。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章