zoukankan      html  css  js  c++  java
  • 【Android

      draw(绘制)过程的作用是将View绘制到屏幕上面。View中有 draw() 方法和 onDraw() 方法,但onDraw()方法是空方法;ViewGroup中没有draw()方法,也没有onDraw()方法。由此可以推测出:ViewGroup的绘制过程调用的流程和View的绘制过程流程是相同的,且和onLayout()、onMeasure()方法一样,因为不同的ViewGroup子类有不同的绘制方式,因此将onDraw()方法下放到ViewGroup的子类中实现。接下来看一下View类的draw()方法的源码:

    /**
     * 在给定的Canvas画布上手动渲染这个View及其所有子元素;
     * 在调用这个方法之前,这个View必须已经经过了layout布局过程;
     * 在自定义View的时候,不能重写这个方法,而应该重写onDraw()方法。
     *
     * @param canvas View渲染的目标画布
     */
    @CallSuper
    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;
        /*
         * 这种遍历绘制的方法需要执行几个步骤,且必须按适当的顺序执行
         * 1. 绘制背景
         * 2. (按需执行)保存画布层以应对褪色
         * 3. 绘制View的内容
         * 4. 绘制View中的子元素
         * 5. (按需执行)绘制褪色边缘并恢复画布层
         * 6. 绘制装饰物(前景、滚动条等)
         */
        // Step 1、绘制背景
        int saveCount;
        if (!dirtyOpaque) {
            drawBackground(canvas);
        }
        // 一般情况下,都会尽量跳过Step2和Stop5
        final int viewFlags = mViewFlags;
        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
        if (!verticalEdges && !horizontalEdges) {
            // Step 3、绘制View中的内容
            if (!dirtyOpaque) onDraw(canvas);
            // Step 4、绘制View中的子元素
            dispatchDraw(canvas);
            // Overlay是View内容的一部分,应该画在前景的底下(先于前景绘制)
            if (mOverlay != null && !mOverlay.isEmpty()) {
                mOverlay.getOverlayView().dispatchDraw(canvas);
            }
            // Step 6、绘制装饰物,如前景、滚动条
            onDrawForeground(canvas);
            // 完成绘制
            return;
        }
    
        /*
         * 我们在下面做了完整的例程:
         * 这是一种不常见的情况,在这种情况中渲染速度不是很重要,因此我们将上面的一些流程又重复了一遍
         */
        // ......代码省略......
    }

      从上面的代码可以看出,View的绘制过程总共分为六个步骤,但大多数情况下,第二步和第五步都会被省略,因此,我们在这里只分析1、3、4、6步骤。这样,View的绘制流程可以总结为: 绘制背景->绘制内容->绘制子元素->绘制其他(前景、滚动条等) ,对应的四个方法分别是: drawBackground() 、 onDraw() 、 dispatchDraw() 、 onDrawForeground() 。其中,onDraw()方法和dispatchDraw()方法在View类中没有实现,需要我们在自定义View中自行重写。

  • 相关阅读:
    CCF-CSP认证 C++题解目录
    LeetCode周赛#205
    LeetCode双周赛#34
    Codeforces Round #667 (Div. 3) B、C、D、E 题解
    Codeforces Round #656 (Div. 3) 题解
    牛客小白月赛#26 题解
    LeetCode周赛#204 题解
    LeetCode周赛#203 题解
    牛客小白月赛#27 题解
    N阶上楼梯问题——动态规划(递推求解)
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6721869.html
Copyright © 2011-2022 走看看