Android绘制流程

相关知识点

LayoutParams

每个自定义的ViewGroup都需要确定添加的子View能够拥有什么样的属性,如MarginLayoutParams,可以通过ViewGroup的generateLayoutParams()方法来自定义ViewGroup的LayoutParams。从这里我们也可以理解,当我们在代码中动态生成布局的时候,父控件如果是LinearLayout,则子控件设置的LayoutParams必须是LinearLayout.LayoutParams。

View的测量模式

  • EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent时,ViewGroup会将其设置为EXACTLY;
  • UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中、ScrollView的childView的heightMode中;此种模式比较少见。
  • AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时,ViewGroup会将其设置为AT_MOST。这种模式下,一般我们要测量控件的实际大小。

View/ViewGroup的职责

View的职责

  • 根据ViewGroup建议的宽高和测量模式计算出自己的宽高
  • 在ViewGroup中制定的区域内绘制自己
  • 所以自定义ViewGroup更多的是在onMeasure(),onDraw()中处理
    注意自定义View更多的是考虑padding值

ViewGroup的职责

  • 给childView计算出建议的宽高和测量模式
  • 决定childView的位置
  • 所以自定义ViewGroup更多的是在onMeasure(),onLayout()中处理,onDraw()交由系统处理
    注意自定义ViewGroup更多的是考虑children的margin

自定义控件绘制的一般流程

自定义View绘制流程

  1. 在onMeasure()中测量自身,主要针对warp_content来测量自己。如果你设计的控件是Match_Parent或是制定的值,则onMeasure()可以省略。
  2. 根据测量的结果在onDraw()中绘制自己

注意,当自定义的View的宽高是Match_parent , 或者具体值的话,则不用复写onMeasure()

自定义ViewGroup绘制流程

  1. 根据childView需要支持的属性自定义LayoutParams
   @Override
   protected LayoutParams generateDefaultLayoutParams()    {
        return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }
    public LayoutParams generateLayoutParams(AttributeSet attrs)    {
        return new MarginLayoutParams(getContext(), attrs);
    }
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p)    {
        return new MarginLayoutParams(p);
    }
  1. onMeasure()中调用measureChildren()来使childView测量自己。如果onMeasure()中测量模式是wrap_content,则需要根据childView的测量结构来决定ViewGroup自己的大小
    //设定自定义View或者ViewGroup在onMeasure()测量的宽高
    setMeasuredDimension(w,h)方法来设定。
    //根据spec(父容器onMeasure提供的宽值),子控件支持的padding,以及子控件自身的大小
    计算出子控件的MeasureSpec类型的值,这个值计算出之后一般就要调用childView.measre().
    getChildMeasureSpec(int spec, int padding, int childDimension)

  2. onLayout中通过childView.layout(cl, ct, cr, cb)来设定childView的布局位置。
    如果子控件支持margin则,计算位置的时候主语考虑margin
    其中的自View的区域通过子View的对应LayouParams(如MarginLayoutParams)来获取自定义ViewGroup的相关类:

自定义控件优化

  • onMeasure(),onLayout(),onDraw()不宜使用局部变量

你可能感兴趣的:(Android绘制流程)