美文网首页
是Android的自定义View-绘制流程-绘制

是Android的自定义View-绘制流程-绘制

作者: redrain39 | 来源:发表于2021-02-03 21:47 被阅读0次

    前言

    performTraversals方法中,执行完layout之后,接下来就要开始进行draw的过程了。

    源码分析

    分析入口

    performTraversals中有这么一个方法是我们分析绘制流程的入口:

    // 执行绘制操作
    performDraw();
    
    private void performDraw() {
        // 核心方法,进行绘制操作  
        // 当然这个方法并不是我们要分析的绘制开始的地方
        // 跳过与本文暂无关系的方法和过程 --> 分析:绘制开始
        boolean canUseAsync = draw(fullRedrawNeeded);
    }
    

    分析:绘制开始

    public void draw(Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
    
        // 绘制的流程:
        // 1.绘制背景
        // 2.绘制内容
        // 3.绘制子控件
        // 4.绘制前景
    
        // 绘制背景
        int saveCount;
        drawBackground(canvas);
    
        ···
    
        boolean drawTop = false;
        boolean drawBottom = false;
        boolean drawLeft = false;
        boolean drawRight = false;
    
        float topFadeStrength = 0.0f;
        float bottomFadeStrength = 0.0f;
        float leftFadeStrength = 0.0f;
        float rightFadeStrength = 0.0f;
    
        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.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
            drawTop = topFadeStrength * fadeHeight > 1.0f;
            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
        }
    
        if (horizontalEdges) {
            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
            drawRight = rightFadeStrength * fadeHeight > 1.0f;
        }
    
        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);
        }
    
        // 绘制内容
        onDraw(canvas);
    
        // 绘制子控件
        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);
        }
    
        // 绘制前景
        onDrawForeground(canvas);
    
        if (debugDraw()) {
            debugDrawFocus(canvas);
        }
    }
    

    绘制的内容暂时就讲这么多,在源码中有很多与绘制流程无关的内容就没有展开来讲,一般的,经过了draw流程之后控件就会展示在我们的面前啦。

    总结

    View的绘制过程:

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

    简单来讲就是从最底层的画布开始绘制:
    背景 -> 控件本身 -> 子控件(同样的顺序)-> 前景

    在日常开发中,一般会覆写onDraw方法来进行自定义视图的绘制:

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 获取到View的canvas
    }
    

    link

    在之后的讲解中,会详细地对绘制进行讲解。

    相关文章

      网友评论

          本文标题:是Android的自定义View-绘制流程-绘制

          本文链接:https://www.haomeiwen.com/subject/jiamtltx.html