自定义View-绘制

绘制

  • 绘制是一个两遍(two pass)的过程:一个measure pass和一个layout pass。
    • 测量过程(measuring pass)是在measure(int, int)中实现的,是从树的顶端由上到下进行的。在这个递归过程中,每一个View会把自己的dimension specifications传递下去。在measure pass的最后,每一个View都存储好了自己的measurements,即测量结果。
    • 第二个是布局过程(layout pass),它发生在 layout(int, int, int, int)中,仍然是从上到下进行(top-down)。

void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

  • 一般情况重写onMeasure()方法作用是为了自定义View尺寸的规则,如果你的自定义View的尺寸是根据父控件行为一致,就不需要重写onMeasure()方法
  • 如果不重写onMeasure方法,那么自定义view的尺寸默认就和父控件一样大小,当然也可以在布局文件里面写死宽高,而重写该方法可以根据自己的需求设置自定义view大小
  • 在覆写onMeasure方法的时候,必须调用 setMeasuredDimension(int,int)来存储这个View经过测量得到的measured width and height。如果没有这么做,将会由measure(int, int)方法抛出一个IllegalStateException。
  • 在ViewGroup中onMeasure()方法中重新设置子view的size,方法如下:
    • void measureChild(View child, int parentWidthMeasureSpec,
      int parentHeightMeasureSpec);设置指定的childView的MeasureSpec
    • void measureChildWithMargins(View child,
      int parentWidthMeasureSpec, int widthUsed,
      int parentHeightMeasureSpec, int heightUsed);设置childView的MeasureSpec时加上了padding和margin的大小,还有指定的额外的widthUsed和heightUsed
    • void measureChildren(int widthMeasureSpec, int heightMeasureSpec);为所有的childView 设置MeasureSpec
  • 参数widthMeasureSpec与heightMeasureSpec虽然是int类型,但却不是表示view的尺寸,而是由 尺寸(size)和模式(mode)进行位运算的组合值。
    • 获取 尺寸(size)的方法:MeasureSpec.getSize(widthMeasureSpec);这个才是view的size
    • 获取 模式(mode)的方法:MeasureSpec.getMode(widthMeasureSpec);Mode类型如下:
      • UNSPECIFIED:父不没有对子施加任何约束,子可以是任意大小(也就是未指定)

      • EXACTLY:父决定子的确切大小,子被限定在给定的边界里,忽略本身想要的大小

      • AT_MOST:子最大可以达到的指定大小,当设置为wrap_content时,模式为AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸

  • 父控件与子控件 MeasureSpec对应关系如下图:
    在这里插入图片描述

void onLayout(boolean changed, int left, int top, int right, int bottom)

  • 自定义ViewGroup中的onLayout()方法中的参数是自身四个顶点的相对于左上角的坐标的差值。
  • 自定义View中的onLayout()方法中的参数是4个顶点相对父布局左上角坐标的差值,View中onLayout()方法的参数说明如下图:

在这里插入图片描述

  • 根据参数通过一定规则计算childview的4个顶点的坐标来设置childview的位置,使用view.layout()方法调用childview的onLayout()方法。
  • layout()方法会计算view的mLeft;mTop;mBottom;mRight 这4个属性的值。相对应的方法是view.getLeft();view.getTop();view.getBottom();view.getRight()其含义如下
    • mLeft:子View左边界到父view左边界的距离
    • mTop:子View上边界到父view上边界的距离
    • mRight:子View右边界到父view左边界的距离
    • mBottom:子View下边距到父View上边界的距离

猜你喜欢

转载自blog.csdn.net/genmenu/article/details/88868533