preface

In the performTraversals method, after layout is executed, the next step is to draw.

Source code analysis

Analysis of the entrance

In FormTraversals there is a method that is the entry point for analyzing the rendering process:

// Perform the draw operation
performDraw();
Copy the code
private void performDraw(a) {
    // Core method to draw operations
    // Of course, this method is not the beginning of our analysis of the drawing
    // Skip methods and procedures that are not related to this article for now --> Analysis: Start drawing
    boolean canUseAsync = draw(fullRedrawNeeded);
}
Copy the code

Analysis: Start drawing

public void draw(Canvas canvas) {
    final int privateFlags = mPrivateFlags;
    mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

    // Draw the process:
    // 1. Draw the background
    // 2. Draw content
    // 3. Draw the child control
    // 4. Draw foreground

    // Draw the background
    intsaveCount; drawBackground(canvas); ...boolean drawTop = false;
    boolean drawBottom = false;
    boolean drawLeft = false;
    boolean drawRight = false;

    float topFadeStrength = 0.0 f;
    float bottomFadeStrength = 0.0 f;
    float leftFadeStrength = 0.0 f;
    float rightFadeStrength = 0.0 f;

    int paddingLeft = mPaddingLeft;

    final boolean offsetRequired = isPaddingOffsetRequired();
    if (offsetRequired) {
        paddingLeft += getLeftPaddingOffset();
    }

    int left = mScrollX + paddingLeft;
    int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
    int top = mScrollY + getFadeTop(offsetRequired);
    int bottom = top + getFadeHeight(offsetRequired);

    if (offsetRequired) {
        right += getRightPaddingOffset();
        bottom += getBottomPaddingOffset();
    }

    final ScrollabilityCache scrollabilityCache = mScrollCache;
    final float fadeHeight = scrollabilityCache.fadingEdgeLength;
    int length = (int) fadeHeight;

    if (verticalEdges && (top + length > bottom - length)) {
        length = (bottom - top) / 2;
    }
    if (horizontalEdges && (left + length > right - length)) {
        length = (right - left) / 2;
    }

    if (verticalEdges) {
        topFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getTopFadingEdgeStrength()));
        drawTop = topFadeStrength * fadeHeight > 1.0 f;
        bottomFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getBottomFadingEdgeStrength()));
        drawBottom = bottomFadeStrength * fadeHeight > 1.0 f;
    }

    if (horizontalEdges) {
        leftFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getLeftFadingEdgeStrength()));
        drawLeft = leftFadeStrength * fadeHeight > 1.0 f;
        rightFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getRightFadingEdgeStrength()));
        drawRight = rightFadeStrength * fadeHeight > 1.0 f;
    }

    saveCount = canvas.getSaveCount();
    int topSaveCount = -1;
    int bottomSaveCount = -1;
    int leftSaveCount = -1;
    int rightSaveCount = -1;

    int solidColor = getSolidColor();
    if (solidColor == 0) {
        if (drawTop) {
            topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
        }

        if (drawBottom) {
            bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
        }

        if (drawLeft) {
            leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
        }

        if(drawRight) { rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom); }}else {
        scrollabilityCache.setFadeColor(solidColor);
    }

    // Draw the content
    onDraw(canvas);

    // Draws a child control
    dispatchDraw(canvas);

    final Paint p = scrollabilityCache.paint;
    final Matrix matrix = scrollabilityCache.matrix;
    final Shader fade = scrollabilityCache.shader;

    if (drawRight) {
        matrix.setScale(1, fadeHeight * rightFadeStrength);
        matrix.postRotate(90);
        matrix.postTranslate(right, top);
        fade.setLocalMatrix(matrix);
        p.setShader(fade);
        if (solidColor == 0) {
            canvas.restoreUnclippedLayer(rightSaveCount, p);

        } else{ canvas.drawRect(right - length, top, right, bottom, p); }}if (drawLeft) {
        matrix.setScale(1, fadeHeight * leftFadeStrength);
        matrix.postRotate(-90);
        matrix.postTranslate(left, top);
        fade.setLocalMatrix(matrix);
        p.setShader(fade);
        if (solidColor == 0) {
            canvas.restoreUnclippedLayer(leftSaveCount, p);
        } else{ canvas.drawRect(left, top, left + length, bottom, p); }}if (drawBottom) {
        matrix.setScale(1, fadeHeight * bottomFadeStrength);
        matrix.postRotate(180);
        matrix.postTranslate(left, bottom);
        fade.setLocalMatrix(matrix);
        p.setShader(fade);
        if (solidColor == 0) {
            canvas.restoreUnclippedLayer(bottomSaveCount, p);
        } else{ canvas.drawRect(left, bottom - length, right, bottom, p); }}if (drawTop) {
        matrix.setScale(1, fadeHeight * topFadeStrength);
        matrix.postTranslate(left, top);
        fade.setLocalMatrix(matrix);
        p.setShader(fade);
        if (solidColor == 0) {
            canvas.restoreUnclippedLayer(topSaveCount, p);
        } else {
            canvas.drawRect(left, top, right, top + length, p);
        }
    }

    canvas.restoreToCount(saveCount);

    drawAutofilledHighlight(canvas);

    if(mOverlay ! =null && !mOverlay.isEmpty()) {
        mOverlay.getOverlayView().dispatchDraw(canvas);
    }

    // Draw foreground
    onDrawForeground(canvas);

    if(debugDraw()) { debugDrawFocus(canvas); }}Copy the code

Draw content for the time being so much, in the source code there are a lot of content unrelated to draw process is not expanded to say, in general, after the draw process control will be displayed in front of us.

conclusion

View drawing process:

  • drawBackground(canvas);
  • onDraw(canvas);
  • dispatchDraw(canvas);
  • onDrawForeground(canvas);

This is simply to start from the lowest canvas: background -> control itself -> child controls (same order) -> foreground

In daily development, the onDraw method is overridden to draw custom views:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // Get the View canvas
}
Copy the code

We’ll cover drawing in more detail later in the tutorial.