-
主體函數(shù)
View.draw,View.drawBackground,View.onDraw,View.dispatchDraw,View.onDrawForeground -
draw(Canvas canvas)- 作用:根據(jù)給定的
Canvas繪制View及其子View,并定義繪制方法的執(zhí)行順序。 - 注意:
-
draw流程前必須完成layout流程 - 所有的視圖最終都是調(diào)用
View.draw來完成繪制(ViewGroup中沒有重寫此方法) - 在自定義
View中,不應(yīng)重寫draw方法,而應(yīng)重寫onDraw方法 - 如果一定要重寫
draw,必須加上super.draw(canvas),再進行自定義繪制
-
- 相關(guān)源碼:
android/view/View.java public void draw(Canvas canvas) { //第一步:繪制背景 drawBackground(canvas); //檢查是否有圖層狀態(tài)保存 final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; //如果沒有,則跳過圖層保存(第二步)恢復(fù)操作(第五步),直接執(zhí)行繪制, //所以,如果沒必要,不要使用save-restore,可以提高繪制效率 if (!verticalEdges && !horizontalEdges) { //第二步:繪制主體 onDraw(canvas); //第三步:繪制子View dispatchDraw(canvas); //第四步:繪制前景(滑動條 前景等) onDrawForeground(canvas); //第五步:繪制焦點高亮處 drawDefaultFocusHighlight(canvas); return; } //如果有圖層狀態(tài),則執(zhí)行下列步驟 //第二步:保存圖層狀態(tài) ... ... 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); //第五步:恢復(fù)圖層狀態(tài) canvas.restoreToCount(saveCount); //第六步:繪制裝飾(前景 滑動條等) onDrawForeground(canvas); }
- 作用:根據(jù)給定的
-
drawBackground(Canvas canvas)- 作用:繪制背景到
Canvas上 - 相關(guān)源碼:
android/view/View.java private void drawBackground(Canvas canvas) { final Drawable background = mBackground; //根據(jù)layout流程后獲取的位置信息來設(shè)置背景邊界 setBackgroundBounds(); //根據(jù)x y是否有偏移量,決定是否需要移動畫布 final int scrollX = mScrollX; final int scrollY = mScrollY; if ((scrollX | scrollY) == 0) { background.draw(canvas); } else { canvas.translate(scrollX, scrollY); //調(diào)用Drawable.draw繪制背景 background.draw(canvas); canvas.translate(-scrollX, -scrollY); } }
- 作用:繪制背景到
-
onDraw(Canvas canvas)- 作用:繪制
View的主體內(nèi)容,自定義View重寫該方法,完成自身的繪制。 - 相關(guān)源碼:
android/view/View.java protected void onDraw(Canvas canvas) {}
- 作用:繪制
-
dispatchDraw(Canvas canvas)- 作用:繪制子
View的內(nèi)容。一般View不需要重寫,ViewGroup可以重寫 - 注意:此方法發(fā)生在自身的
onDraw之后,但發(fā)生在子View的draw前 - 相關(guān)源碼:
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) { //調(diào)用子View.draw return child.draw(canvas, this, drawingTime); }
- 作用:繪制子
-
onDrawForeground(Canvas canvas)- 作用:繪制前景(滑動條 前景等),繪制在
View的頂部。 - 相關(guān)源碼:
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方法,則可以設(shè)置為true,某一些ViewGroup會設(shè)置為true以進行優(yōu)化繪制。
-
- 系列文章
