View繪製流程簡介

簡單梳理一下View的繪製流程。View的繪製分爲三個部分(mechanism),分別爲:measure,layout,draw。


第一部分:Measure

這一過程負責確定各個View的大小,得到的結果存放在每個ViewmMeasuredWidthmMeasuredHeight中。

該部分主要有三個函數:

measure(int widthMeasureSpec, int heightMeasureSpec);
onMeasure(int widthMeasureSpec, int heightMeasureSpec);
setMeasuredDimension(int measuredWidth, int measuredHeight);

measure(int, int)

發起measure過程,需要用到兩類信息:

  1. MeasureSpecs,父View對子View的要求,有三種模式:UNSPECIFIEDEXACTLYAT_MOST
  2. ViewGroup.LayoutParams,子View自身的佈局參數,可以是具體值、MATCH_PARENTWRAP_CONTENT

該方法爲final方法,不可被Override,該方法會調用onMeasure(),一般情況下子類應該Override onMeasure()方法。

onMeasure(int, int)

進行具體的測量工作,該函數的參數是mMeasuredWidthmMeasuredHeight,即父View對我們的測量要求,要做的工作就是根據父View的大小確定自己的大小。如果是ViewGroup,還要調用子Viewmeasure(int, int)才能確定自己的大小。同時這一步的最後需要調用setMeasuredDimension(int, int)將測量結果存儲起來,否則在使用過程中會拋出異常。

setMeasuredDimension(int, int)

將測量結果存儲在mMeasuredWidthmMeasuredHeight中,在之後的步驟中,可以通過getMeasuredWidth()getMeasuredHeight()獲取這兩個參數。


第二部分:Layout

這一部分通過Measure中得到的各個View的大小,確定各個View的擺放位置。

該部分主要有兩個函數:

layout(int l, int t, int r, int b);
onLayout(boolean changed, int l, int t, int r, int b);

相對於measure,這部分比較簡單,最後會通過setFrame(int, int, int, int)確定各個View相對於父View的座標。

第三部分:Draw

該部分繪製View的內容。

主要有兩個函數:

draw(Canvas canvas);
onDraw(Canva canvas);

draw(Canvas)

代碼略長,但主要工作是調用onDraw()繪製自己,然後調用dispatchDraw()繪製子View

根據文檔說明,該方法負責渲染將View以及所有子View渲染到Canvas,必須在layout完成後調用,一般不應該Override該方法,如果要繼承,可以Override onDraw()方法。

也就是說自定義View的時候基本可以不考慮這個方法。

onDraw(Canvas)

ViewonDraw()方法爲空實現,subclass一般要Override該方法,繪製自己。

比如,想繪製一個矩形:

// 畫一個起點座標(0,0),終點座標(10,20)的矩形
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, 10, 20, paint);

dispatchDraw(Canvas)

調用子Viewdraw()方法,繪製子View

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章