Android中dispatchDraw分析

Android中dispatchDraw分析

View中:

public void draw(Canvas canvas) {

/*

1. Draw the background   绘制背景

2. If necessary, save the canvas' layers to prepare for fading  如有必要,颜色渐变淡之前保存画布层(即锁定原有的画布内容)

3. Draw view's content  绘制view的内容

4. Draw children    绘制子view

5. If necessary, draw the fading edges and restore layers   如有必要,绘制颜色渐变淡的边框,并恢复画布(即画布改变的内容附加到原有内容上)

6. Draw decorations (scrollbars for instance)   绘制装饰,比如滚动条

*/

   ...

   if (!dirtyOpaque) {

       drawBackground(canvas); //背景绘制

   }

   // skip step 2 & 5 if possible (common case) 通常情况跳过第2和第5步

   ...

   if (!dirtyOpaque) onDraw(canvas); //调用onDraw

   dispatchDraw(canvas);   //绘制子view

   onDrawScrollBars(canvas); //绘制滚动条

   ...

}

protected void dispatchDraw(Canvas canvas) { //空实现 }

protected void onDraw(Canvas canvas) { //空实现 }


ViewGroup中:

protected void dispatchDraw(Canvas canvas) {

    ...

    drawChild(...); //绘制子view

    ...

}


protected boolean drawChild(Canvas canvas, View child, long drawingTime) {

        return child.draw(canvas, this, drawingTime);

}



说明:

1. 自定义一个view时,重写onDraw。

    调用view.invalidate(),会触发onDraw和computeScroll()。前提是该view被附加在当前窗口上

    view.postInvalidate(); //是在非UI线程上调用的


2.  自定义一个ViewGroup,重写onDraw。

     onDraw可能不会被调用,原因是需要先设置一个背景(颜色或图)。

           表示这个group有东西需要绘制了,才会触发draw,之后是onDraw。

    因此,一般直接重写dispatchDraw来绘制viewGroup


3. 自定义一个ViewGroup

    dispatchDraw会调用drawChild。


总结:

绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现

绘制自己的孩子通过dispatchDraw(canvas)实现


    View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小
     画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(), getIntrinsicHeight()方法,然后设为背景。

你可能感兴趣的:(Android)