一、Canvas概念
画布,应用程序绘制图形以及控制图形的动画都是在其上面实现的,它提供了图形绘制的真实表面和绘制图形相关的接口,你的绘画操作真正通过它被渲染在窗口的Bitmap上,使得用户可见。
在View的OnDraw回调事件里,可以获得当前View的Canvas;对于SurfaceView对象你也可以通过 SurfaceHolder.lockCanvas()来获得Canvas;假如你需要创建的一个新的Canvas,你首先需要创建的一个用于真正绘制的Bitmap,通过Bitmap来创建Canvas,代码如下:
Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
二、Canvas与View之间的关系
在应用程序窗口的绘制过程中,可以逐步理解到Canvas和View之间的关系。
首先由该窗口的ViewRootImpl通过SurfaceHolder.lockCanvas()来获得创建一个Canvas,并把该Canvas传给窗口的DecorView的draw方法,源代码如下:
/**
* Manually render this view (and all of its children) to the given Canvas.
* The view must have already done a full layout before this function is
* called. When implementing a view, implement
* {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
* If you do need to override this method, call the superclass version.
*
* @param canvas The Canvas to which the View is rendered.
*/
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;
/*
* 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
* 4. Draw children
* 5. If necessary, draw the fading edges and restore layers
* 6. Draw decorations (scrollbars for instance)
*/
// Step 1, draw the background, if needed
int saveCount;
if (!dirtyOpaque) {
drawBackground(canvas);
}
.......
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
.......
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
}
接下来通过dispatchDraw(canvas)分发给窗口的子View,源代码如下:
@Override
protected void dispatchDraw(Canvas canvas) {
.........
// We will draw our child's animation, let's