Android的View绘图过程

         最近两天研究了View是如何绘制的代码,小记如下:

View的绘制,要从ViewRootImpl这个类说起(曾经的ViewRoot,3.0还是4.0之后更名),ViewRootImpl并不是一个View类,那么为什么叫他root呢?因为绘制的动作是从它这里发起的,下面我们会讲它的一个重要的函数performTraversals,其中一个重要作用就是发起了View的绘制,View这棵树就从这里开始生根发芽。

         

         这里补充一下基础知识,android的View层次是一个树状结构,每一个父节点担任起绘制自己和自己儿子节点的任务。

View怎么绘制自己呢

         答案是onDraw函数。我们看View的实现中,ondraw是一个空的方法体,凡是它的子类必须实现它以完成绘制自己的功能,例子可以参照TextView。

         那么,在这棵View树上,一些节点是有子节点的,他们就是ViewGroup,很形象的名称,我开始还觉得ViewGroup不常用到,实际上像ListView就是一个典型的ViewGroup,它能包含其他的View就是这个道理。

ViewGroup是怎么绘制子节点的

         这起源于dispatchDraw函数,这个函数又是被谁调用我们暂且搁着后面再讲。dispatchDraw的作用顾名思义,就是把绘制的事件发放出来,说“你你你,去把自个儿画出来“,这个函数一般会被重载,例子可以参照ListView。如果子节点也是一个ViewGroup,此过程会迭代的走下去,此恨绵绵无绝期阿~~直到最底层的一个叶子节点。


         OK,回到正题,我其实想讲的是ViewRootImpl这位祖师爷是如何让这套机制按部就班的进行的,我们来看看ViewRootImpl内部是如何发起绘制的。

         最开始我们说到performTraversals这个函数,这个函数确实是牛逼哄哄的,它有800多行,有兴趣的同学可以去看看它老人家。好吧,其实我也没耐心看完,它的作用大致可以分为三大块,Measure(计算视图大小),Layout(开始布局),draw(绘制),前面两大块不是我此篇的重点,最后的一块draw是我今天研究的。

         请在performTraversals函数中搜出mView.draw,是的,它就是这棵树绘制的开始啦,进入到View的draw函数中,我们从注释中就能看到它有6个步骤

        /*
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *
         *      1. Draw the background   //绘制背景
         *      2. If necessary, save the canvas' layers to prepare for fading  //如果需要,为边缘渐变做一些准备
         *      3. Draw view's content   //绘制View自己的内容(重要)
         *      4. Draw children  //绘制子节点(重要)
         *      5. If necessary, draw the fading edges and restore layers //如果需要,绘制渐变边缘和恢复图层
         *      6. Draw decorations (scrollbars for instance)  //绘制一些装饰,比如说滚动条
         */


           第三与第四步是关键,那就是绘制自己和绘制子节点。下面的代码告诉我们,绘制开始了。

        // 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
            if (!dirtyOpaque) onDraw(canvas);

            // Step 4, draw the children
            dispatchDraw(canvas);

            // Step 6, draw decorations (scrollbars)
            onDrawScrollBars(canvas);

            // we're done...
            return;
        }

到此为止,视图是如何绘制出来的一个来龙去脉就清晰了。先写到这里把

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值