美文网首页
Android View的工作流程- draw过程

Android View的工作流程- draw过程

作者: BlueSocks | 来源:发表于2023-07-31 16:26 被阅读0次

    View的draw过程主要是将View绘制到屏幕上面,View的draw过程遵循如下几步:

    • 绘制背景:drawBackground
    • 绘制自己:onDraw
    • 绘制子元素:dispatchDraw
    • 绘制滑动边缘渐变和滑动条,绘制前景:onDrawForeground

    这一点通过draw方法的源码可以明显看出来,如下:

    public void draw(Canvas canvas) {
        final int privateFlags = mPrivateFlags;
        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
        int saveCount;
    
        //绘制背景
        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
            //绘制自己
            onDraw(canvas);
    
            // Step 4, draw the children
            //绘制子元素
            dispatchDraw(canvas);
    
            drawAutofilledHighlight(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);
    
            // Step 7, draw the default focus highlight
            drawDefaultFocusHighlight(canvas);
    
            if (isShowingLayoutBounds()) {
                debugDrawFocus(canvas);
            }
    
            // we're done...
            return;
        }
        ...
    }
    
    

    View绘制过程的传递是dispatchDraw来实现的,dispatchDraw会遍历所有的子元素,如此draw事件就一层层地传递了下去。

    View有一个特殊的方法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);
    }
    
    

    从setWillNotDraw这个方法的注释中可以看出,如果一个View不需要绘制任何内容,那么设置这个标记位为true以后,系统会进行相应的优化。默认情况下,View没有启用这个优化标记位,但是ViewGroup会默认启用这个优化标记位。这个标记位对实际开发的意义是:当我们自定义控件继承于ViewGroup并且本身不具备绘制功能时,就可以开启这个标记位从而便于系统进行后续的优化。当然,当明确知道一个ViewGroup需要通过onDraw来绘制内容时,我们需要显式的关闭WILL_NOT_DRAW这个标记位。

    相关文章

      网友评论

          本文标题:Android View的工作流程- draw过程

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