Twenty-two, View works (6) --- View of the draw process

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/yz_cfm/article/details/91047638

    Learning the two front View of the three processes: measure the process (determining a measurement View width and height), (width and height determined View and final positions of the four vertices) layout process. The following learning process View --- draw last three processes of (drawing).

    The following look at View the draw () method implementation:

/**
 * 实现视图时,请执行 onDraw() 方法,而不是覆盖这个方法。如果确实需要重写此方法,请调用超类版本
 */
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 遍历执行几个必须执行的绘图步骤
     * 按适当次序:
     *      1. 绘制背景( background.draw(canvas) )
     *      2. 如有必要,保存画布的图层以防淡化
     *      3. 绘制自己的内容( onDraw() )
     *      4. 绘制 children( dispatchDraw() )
     *      5. 如有必要,绘制淡化边缘并恢复图层
     *      6. 绘制装饰( 例如 scrollbars -> onDrawScrollBars() )
     */
    // Step 1, 绘制背景
    int saveCount;

    if (!dirtyOpaque) {
        drawBackground(canvas);
    }

    // skip step 2 & 5 if possible (common case)
    ...
    if (!verticalEdges && !horizontalEdges) {
        // Step 3, 绘制自己
        if (!dirtyOpaque) onDraw(canvas);

        // Step 4, 绘制 children
        dispatchDraw(canvas);
        ...

        // Step 6, 绘制装饰(前景,滚动条)
        onDrawForeground(canvas);

        // Step 7, 绘制默认焦点高亮显示
        drawDefaultFocusHighlight(canvas);

        if (debugDraw()) {
            debugDrawFocus(canvas);
        }

        // we're done...
        return;
    }
    ...
    // Step 2, 保存画布的图层
    ...
    if (solidColor == 0) {
        ...
        if (drawTop) {
            canvas.saveLayer(left, top, right, top + length, null, flags);
        }

        if (drawBottom) {
            canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
        }

        if (drawLeft) {
            canvas.saveLayer(left, top, left + length, bottom, null, flags);
        }

        if (drawRight) {
            canvas.saveLayer(right - length, top, right, bottom, null, flags);
        }
    } else {
        scrollabilityCache.setFadeColor(solidColor);
    }

    // Step 3, 绘制自己
    if (!dirtyOpaque) onDraw(canvas);

    // Step 4, 绘制 children
    dispatchDraw(canvas);

    // Step 5, 绘制淡入淡出效果并恢复图层
    ...
    if (drawTop) {
        ...
        canvas.drawRect(left, top, right, top + length, p);
    }

    if (drawBottom) {
        ...
        canvas.drawRect(left, bottom - length, right, bottom, p);
    }

    if (drawLeft) {
        ...
        canvas.drawRect(left, top, left + length, bottom, p);
    }

    if (drawRight) {
        ...
        canvas.drawRect(right - length, top, right, bottom, p);
    }

    canvas.restoreToCount(saveCount);
    drawAutofilledHighlight(canvas);

    // Step 6, 绘制装饰(前景,滚动条)
    onDrawForeground(canvas);

    if (debugDraw()) {
        debugDrawFocus(canvas);
    }
}

    Can be seen from the above, the drawing process is passed through View dispatchDraw () implementation:

protected void dispatchDraw(Canvas canvas) {
    ...
    for (int i = 0; i < childrenCount; i++) {
        while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
            ...
            if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                    transientChild.getAnimation() != null) {
                more |= drawChild(canvas, transientChild, drawingTime);
            }
            ...
        }
        ...
        if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
            more |= drawChild(canvas, child, drawingTime);
        }
    }
}

    Then dispatchDraw () in turn calls drawChild ():

protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
    return child.draw(canvas, this, drawingTime);
}

    Next drawChild () call to continued draw () method of the View, and so forth, will be transfer layers, to complete the entire process of drawing View tree.


    A special method --- setWillNotDraw () View of a see below.

/**
 * 如果该 View 本身不需要绘制任何内容,那么设置这个标记位为 true 以后,系统会进行相应的优化。
 * 默认情况下,View 没有启用这个优化标志位,但是它的子类 ViewGroup 默认会启用这个优化标志位。
 */
public void setWillNotDraw(boolean willNotDraw) {
    setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}

ViewGroup.java:

private void initViewGroup() {
    // ViewGroup doesn't draw by default
    if (!debugDraw()) {
        setFlags(WILL_NOT_DRAW, DRAW_MASK);
    }
  ...
}

   So, when we inherit custom control itself does not have to ViewGroup and drawing functions, you can leave it, this is enabled by default optimization flag; but if we need to draw content through onDraw, we need to explicitly close WILL_NOT_DRAW this flag bits, for example you can call in its constructor:

setWillNotDraw(false);

 

Guess you like

Origin blog.csdn.net/yz_cfm/article/details/91047638