View的工作原理之draw

来源:互联网 发布:epson机器人编程 编辑:程序博客网 时间:2024/05/21 06:20

一.概述

相对前面的测量,布置这里的画就很简单了

大致的步骤如下:

1.绘制背景drawBackground(canvas)

2.绘制自己(onDraw)

3.绘制children(dispatchDraw)

4.绘制装饰(onDrawScrollBars)

下面是draw的具体代码,这里分了6部分,但是渐变边缘不一定有,所以简化为上面的四步。

    public void draw(Canvas canvas) {        final int privateFlags = mPrivateFlags;        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;        /*下面就是给的提示步骤         * Draw traversal performs several drawing steps which must be executed         * in the appropriate order:         *         *      1. Draw the background         *      2. If necessary, save the canvas' layers to prepare for fading         *      3. Draw view's content         *      4. Draw children         *      5. If necessary, draw the fading edges and restore layers         *      6. Draw decorations (scrollbars for instance)         */        //第一步:绘制背景        // Step 1, draw the background, if needed        int saveCount;        if (!dirtyOpaque) {            drawBackground(canvas);        }        //第二步和第五步保存和画边缘的渐变效果        // skip step 2 & 5 if possible (common case)        final int viewFlags = mViewFlags;        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;        if (!verticalEdges && !horizontalEdges) {            //第三步.画自己的内容            // Step 3, draw the content            if (!dirtyOpaque) onDraw(canvas);            //第三步.画子view            // Step 4, draw the children            dispatchDraw(canvas);            // Overlay is part of the content and draws beneath Foreground            if (mOverlay != null && !mOverlay.isEmpty()) {                mOverlay.getOverlayView().dispatchDraw(canvas);            }            //第六步,画装饰            // Step 6, draw decorations (foreground, scrollbars)            onDrawForeground(canvas);            // we're done...            return;        }    }

二.需要注意的点

ViewGroup默认情况下,出于性能考虑,会被设置成WILL_NOT_DROW,这样,ondraw就不会被执行了。具体代码如下:

public ViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {   super(context, attrs, defStyleAttr, defStyleRes);    initViewGroup();    initFromAttributes(context, attrs, defStyleAttr, defStyleRes);}private void initViewGroup() {   // ViewGroup doesn't draw by default    if (!debugDraw()) {        setFlags(WILL_NOT_DRAW, DRAW_MASK);    }}

如果我们想重写一个viewgroup的ondraw方法,我们可以在构造函数中,调setWillNotDraw(false),去掉其WILL_NOT_DRAW flag。

三.目前为止View的measure,layout,draw就都从源码角度分析完了,想灵活运用没别的方法自己动手多写,我也会去尝试多造轮子。

原创粉丝点击