View的draw过程源码分析

简介: /** * * 原创作者: * 谷哥的小弟 http://blog.csdn.net/lfdfhl * * 文档描述: * View的draw过程源码分析 * * 绘制过程分为六步: * * 1.


/**
     * 
     * 原创作者: 
	 * 谷哥的小弟 http://blog.csdn.net/lfdfhl 
	 * 
	 * 文档描述:
	 * View的draw过程源码分析
	 * 
	 * 绘制过程分为六步:
	 * 
     * 1. Draw the background
     * 2. If necessary, save the canvas' layers to prepare for fading
     * 3. Draw view's content
     * 4. Draw children
     * 5. If necessary, draw the fading edges and restore layers
     * 6. Draw decorations (scrollbars for instance)
     * 
     * 其中第2步和第5步可以忽略,正如源码中所说的: 
     * skip step 2 & 5 if possible (common case)
     * 
     * 所以关注的是第1,3,4,6步.
     * 
     */
    public void draw(Canvas canvas) {
        if (ViewDebug.TRACE_HIERARCHY) {
            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
        }

        final int privateFlags = mPrivateFlags;
        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
        
        /**
         * 第1步:
         * draw the background, if needed
         * 绘制View的背景
         */
        int saveCount;

        if (!dirtyOpaque) {
            final Drawable background = mBGDrawable;
            if (background != null) {
                final int scrollX = mScrollX;
                final int scrollY = mScrollY;

                if (mBackgroundSizeChanged) {
                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
                    mBackgroundSizeChanged = false;
                }

                if ((scrollX | scrollY) == 0) {
                    background.draw(canvas);
                } else {
                    canvas.translate(scrollX, scrollY);
                    background.draw(canvas);
                    canvas.translate(-scrollX, -scrollY);
                }
            }
        }

        /**
         * 第2,5步:
         * 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) {
        	/**
        	 * 第3步:
        	 * draw the content
        	 * 调用onDraw()绘制View的内容
        	 * 在View和ViewGroup的源码中onDraw方法均为空.
        	 * 因为每个View的内容不同,所以需要由具体的子类去实现
        	 */
            if (!dirtyOpaque) onDraw(canvas);

            /**
             * 第4步:
             * draw the children.
             * 调用dispatchDraw()绘制View的子View.
             * 在View中dispatchDraw()方法是一个空方法,因为View没有孩子.
             * 但是ViewGroup重写了该方法,因为ViewGroup有子View
             */
            dispatchDraw(canvas);

            /**
             * 第6步:
             * draw decorations (scrollbars)
             * 绘制View的滚动条.
             * 其实View都是有滚动条的,但一般情况下将其隐藏了,没有显示
             */
            onDrawScrollBars(canvas);

            return;
        }
        
        
        //省略其余代码.........
        //省略其余代码.........
        //省略其余代码.........
        //省略其余代码.........
       
    }


相关文章
|
5月前
|
Android开发
Android面试题之View的invalidate方法和postInvalidate方法有什么区别
本文探讨了Android自定义View中`invalidate()`和`postInvalidate()`的区别。`invalidate()`在UI线程中刷新View,而`postInvalidate()`用于非UI线程,通过消息机制切换到UI线程执行`invalidate()`。源码分析显示,`postInvalidate()`最终调用`ViewRootImpl`的`dispatchInvalidateDelayed`,通过Handler发送消息到UI线程执行刷新。
63 1
|
7月前
|
XML 前端开发 数据可视化
View的绘制流程
View的绘制流程
45 1
|
7月前
|
前端开发 Android开发 容器
自定义View之View的工作原理
自定义View之View的工作原理
58 0
|
存储 缓存
RecyclerView 动画原理 | 换个姿势看源码(pre-layout)
RecyclerView 动画原理 | 换个姿势看源码(pre-layout)
81 0
|
Android开发
View事件分发相关结论的源码解析
View事件分发的三个核心方法有三个,分别是`dispatchTouchEvent`方法,`onInterceptTouchEvent`方法和`onInterceptTouchEvent`方法。 dispatchTouchEvent方法主要用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。 onInterceptTouchEvent方法在dispatchTouchEvent方法内部调用,用来判断是否拦截某个事件,返回结果表示是否拦截
|
前端开发 Android开发
图+源码,读懂View的Draw方法(一)
本文将继续讲述 View 绘制三大方法的最后一个方法——Draw 方法。该方法不会很复杂,相信大家很快可以弄懂。
图+源码,读懂View的Draw方法(一)
图+源码,读懂View的Draw方法(二)
本文将继续讲述 View 绘制三大方法的最后一个方法——Draw 方法。该方法不会很复杂,相信大家很快可以弄懂。
图+源码,读懂View的Draw方法(二)
|
Android开发
图+源码,读懂View的Measure方法
本篇是 读懂View 系列的第二篇文章,本文将给大家正式开始讲解View绘制的三大方法,本篇将讲述第一个方法—— Measure 方法。
图+源码,读懂View的Measure方法
|
Android开发
图+源码,读懂View的Layout方法
本篇文章就带大家学习 View 绘制三大方法的第二个方法——Layout 方法。
图+源码,读懂View的Layout方法
|
Android开发 容器
View工作原理分析1 - 初识ViewRoot和 DecorView
以下相关资料均来自 Android艺术探索,部分内容加入了一些我个人的理解。
151 0