View Draw 简要过程

2016-11-27  本文已影响58人  zhaoyubetter

draw 就是将view绘制到屏幕上,一般有如下步骤:

  1. 绘制其背景(backgroupDrawable.draw(canvas));
  2. 绘制自己(onDraw);
  3. 绘制子view(dispatchDraw)
  4. 绘制装饰(onDrawScrollBars)

view的draw方法代码片段

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);

            // 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;
        }

View的绘制过程传递 通过 dispatchDraw方法来实现,dispatchDraw遍历调用所有子view元素的draw方法,这样draw事件就传递下去;

setWillNotDraw 方法

/**
     * If this view doesn't do any drawing on its own, set this flag to
     * allow further optimizations. By default, this flag is not set on
     * View, but could be set on some View subclasses such as ViewGroup.
     *
     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
     * you should clear this flag.
     *
     * @param willNotDraw whether or not this View draw on its own
     */
    public void setWillNotDraw(boolean willNotDraw) {
        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
    }

如果View不需要绘制任何内容,可设置此标记为true,系统会进行相关优化;
默认情况下,view没有启动此标志,但viewgroup默认启动这个优化标志,
实际操作场景是:当自定义控件继承自viewgroup,且本身不具备绘制功能时,就可开启此标记,便于系统优化;viewGroup 需要draw时,也得显示的关闭WILL_NOT_DRAW这个标记位;

上一篇下一篇

猜你喜欢

热点阅读