View的工作流程(layout过程)

来源:互联网 发布:mac能玩gta5 编辑:程序博客网 时间:2024/05/22 01:53

layout过程

Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup位置被确定后,它在onLayout中会遍历所有的子元素并调用其layout方法,在layout方法中onLayout方法又会被调用。layout方法确定本身的位置,而onLayout方法则会确定所有子元素的位置。

 public void layout(int l, int t, int r, int b) {        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;        }        int oldL = mLeft;        int oldT = mTop;        int oldB = mBottom;        int oldR = mRight;        boolean changed = isLayoutModeOptical(mParent) ?                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {            onLayout(changed, l, t, r, b);            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnLayoutChangeListeners != null) {                ArrayList<OnLayoutChangeListener> listenersCopy =                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();                int numListeners = listenersCopy.size();                for (int i = 0; i < numListeners; ++i) {                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);                }            }        }        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;    }

大致流程为:首先会通过setFrame方法来设定View的四个顶点的位置,初始化mLeft、mTop、mBottom、mRight这四个值,View的四个顶点一旦确定,那么View在父容器中的位置也就定了;接着会调用onLayout方法,这个方法的用途是父容器确定子元素的位置,和onMeasure方法类似,onLayout的具体实现同样和具体布局有关,所以View和ViewGroup均没有实现onLayout方法。
View的getMeasuredWidth和getWidth的区别:
在View默认的实现中,View的测量宽高和最终宽高是相等的,只不过测量宽高形成于View的measure过程,而最终宽高形成于View的layout过程。

draw过程

View的绘制过程遵循以下几步:

  1. 绘制背景background.draw(canvas);
  2. 绘制自己(onDraw);
  3. 绘制children(dipatchDraw)
  4. 绘制装饰(onDrawScrollBars)

View绘制过程的传递是通过dispatchDraw来实现的,dispatchDraw会遍历调用所有子元素的draw方法。View有一个特殊的方法setWillNotDraw。
如果一个View不需要绘制任何内容,那么设置这个标记位为true以后,系统会进行相应的优化。默认情况下,View没有启用这个优化标记位,但是ViewGroup会默认启用这个优化标记位。这个标记位对实际开发的意义是:当我们的自定义控件继承于ViewGroup并且本身不具备绘制功能时,就可以开启这个标记位,从而便于系统进行后续的优化。

0 0
原创粉丝点击