android 为何设置view为wrap_content但是实际布局大小为match_parent

描述

当我们在设置view的宽高的时候,有时候我们明明设置的是wrap_content,但是却得到了match_parent的效果,特别是我们自定义view的时候,经常碰到这种情况。之前都觉得很神奇,后边慢慢看view的绘制流程以及看源码总算是弄明白原因了。

总的来说是在view.measure方法里调用了onMeasure方法,然后onMeasure方法又调用了setMeasureDimension方法,
此时setMeasureDimension方法传入的参数是通过getDefaultSize方法获取到的精确的尺寸大小,而getDefaultSize(size,measureSpec)
传入的参数size是getSuggestedMinimumWidth的返回值大小(如果背景宽度为null则返回minWidth,不为null则获取max(mBackground.getMiniwidth,minWidth)中一个比较大的值
传入的参数measureSpec为child.measure(widthSpec,heightSpec)的参数
getDefaultSize的具体实现是

int result = size;
  int specMode = MeasureSpec.getMode(measureSpec);
  int specSize = MeasureSpec.getSize(measureSpec);
  switch(specMode){
     case MeasureSpec.UNSPECIFIED:
         result = size;
         break;
      case MeasureSpec.AT_MOST:
      case MeasureSpec.EXACTLY:
         result = specSize;
         break;
  }

会发现当我们设置view或者viewgroup的宽高为wrap_content的时候,默认就是match_parent的效果
原因就在getDefaultSize里google工程师默认的把AT_MOST和EXACTLY做相同的处理了。

解决

那么如何解决view的wrap_content的情况呢?直接调用setMeasureDimension()传入一个默认的size
那么如何解决viewGroup的wrap_content的情况呢?默认的viewGroup的measure方法里有一句super.onMeasure(WidthMeasureSpec,heightMeasureSpec);
这时候我们需要在super之前人为的重新生成一个measureSpec,替换viewGroup原来的measureSpec
那么如何生成一个measureSpec呢?
通过MeasureSpec.makeMeasureSpec(size,mode)来生成,聪明的你肯定
会问那么这里传入的size和mode值是多少呢?
如果说我们想要获取当前view的wrap_content大小,则通过MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED)来生成。

这篇文章分析的更加详细

猜你喜欢

转载自blog.csdn.net/u010648159/article/details/81112643