View工作原理之layout与draw的过程

参考资料:
《Android开发艺术探索》

Layout过程##

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

View.layout方法如下:

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;

       // setFrame 设置View的4个顶点位置,初始化 mLeft 等4个值;
        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 listenersCopy =
                        (ArrayList)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;
    }

layout方法大致流程如下:

  1. 通过setFrame来设置View的4个顶点的位置,即:mLeft,mTop,mRight,mBottom,用来确定View的位置;
  2. 接着调用onLayout方法,来确定子的位置;

Draw的过程##

draw的作用就是将View绘制到屏幕上;具体遵循:

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

setWillNotDraw的说明####

如果一个View不需要绘制任何内容,设置此标志,系统会进行相应的优化;
默认情况下,View没有启动这个优化标志;
默认情况下,ViewGroup启用了这个标志;

当自定义控件继承自ViewGroup时并且本身不具备绘制功能时,可开启这个标记位;
如果自定义的ViewGroup需要通过onDraw来绘制内容时,就需要显示关闭这个标记位;

如在LinearLayout中:

 setWillNotDraw(divider == null);    // divider不为空是,ViewGroup的onDraw将会调用

 @Override
    protected void onDraw(Canvas canvas) {
        if (mDivider == null) {
            return;
        }

        if (mOrientation == VERTICAL) {
            drawDividersVertical(canvas);
        } else {
            drawDividersHorizontal(canvas);
        }
    }

你可能感兴趣的:(View工作原理之layout与draw的过程)