-
主体函数
View.draw,View.drawBackground,View.onDraw,View.dispatchDraw,View.onDrawForeground -
draw(Canvas canvas)- 作用:根据给定的
Canvas绘制View及其子View,并定义绘制方法的执行顺序。 - 注意:
-
draw流程前必须完成layout流程 - 所有的视图最终都是调用
View.draw来完成绘制(ViewGroup中没有重写此方法) - 在自定义
View中,不应重写draw方法,而应重写onDraw方法 - 如果一定要重写
draw,必须加上super.draw(canvas),再进行自定义绘制
-
- 相关源码:
android/view/View.java public void draw(Canvas canvas) { //第一步:绘制背景 drawBackground(canvas); //检查是否有图层状态保存 final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; //如果没有,则跳过图层保存(第二步)恢复操作(第五步),直接执行绘制, //所以,如果没必要,不要使用save-restore,可以提高绘制效率 if (!verticalEdges && !horizontalEdges) { //第二步:绘制主体 onDraw(canvas); //第三步:绘制子View dispatchDraw(canvas); //第四步:绘制前景(滑动条 前景等) onDrawForeground(canvas); //第五步:绘制焦点高亮处 drawDefaultFocusHighlight(canvas); return; } //如果有图层状态,则执行下列步骤 //第二步:保存图层状态 ... ... if (drawTop) { topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length); } if (drawBottom) { bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom); } if (drawLeft) { leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom); } if (drawRight) { rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom); } //第三步:绘制主体 onDraw(canvas); //第四步:绘制子view dispatchDraw(canvas); //第五步:恢复图层状态 canvas.restoreToCount(saveCount); //第六步:绘制装饰(前景 滑动条等) onDrawForeground(canvas); }
- 作用:根据给定的
-
drawBackground(Canvas canvas)- 作用:绘制背景到
Canvas上 - 相关源码:
android/view/View.java private void drawBackground(Canvas canvas) { final Drawable background = mBackground; //根据layout流程后获取的位置信息来设置背景边界 setBackgroundBounds(); //根据x y是否有偏移量,决定是否需要移动画布 final int scrollX = mScrollX; final int scrollY = mScrollY; if ((scrollX | scrollY) == 0) { background.draw(canvas); } else { canvas.translate(scrollX, scrollY); //调用Drawable.draw绘制背景 background.draw(canvas); canvas.translate(-scrollX, -scrollY); } }
- 作用:绘制背景到
-
onDraw(Canvas canvas)- 作用:绘制
View的主体内容,自定义View重写该方法,完成自身的绘制。 - 相关源码:
android/view/View.java protected void onDraw(Canvas canvas) {}
- 作用:绘制
-
dispatchDraw(Canvas canvas)- 作用:绘制子
View的内容。一般View不需要重写,ViewGroup可以重写 - 注意:此方法发生在自身的
onDraw之后,但发生在子View的draw前 - 相关源码:
android/view/View.java protected void dispatchDraw(Canvas canvas) {}android/view/ViewGroup.java protected void dispatchDraw(Canvas canvas) { ... ... //绘制子view more |= drawChild(canvas, transientChild, drawingTime); ... ... } protected boolean drawChild(Canvas canvas, View child, long drawingTime) { //调用子View.draw return child.draw(canvas, this, drawingTime); }
- 作用:绘制子
-
onDrawForeground(Canvas canvas)- 作用:绘制前景(滑动条 前景等),绘制在
View的顶部。 - 相关源码:
public void onDrawForeground(Canvas canvas) { //绘制滚动条及指示器 onDrawScrollIndicators(canvas); onDrawScrollBars(canvas); final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; if (foreground != null) { //绘制前景 foreground.draw(canvas); } }
- 作用:绘制前景(滑动条 前景等),绘制在
-
简要流程
draw主体流程

viewGroup与view层级间的draw流程
-
其他要点
-
View.setWillNotDraw(boolean willNotDraw):如果这个View不需要绘制自身,即onDraw方法,则可以设置为true,某一些ViewGroup会设置为true以进行优化绘制。
-
- 系列文章

