Canvas 在 ViewGroup 與 View 之間的變換

分析 draw 過程的源碼的時候,遇到一個很神奇的疑問:

ViewGroup.dispatchDraw 調(diào)用 dispatchDraw(Canvas) 的時候調(diào)用 View.draw 繪制子 View。將自己的 Canvas, 直接傳給了子 View。此時,Canvas 的繪圖區(qū)域應該是父 View 的繪圖區(qū)域(坐標系)。但是,View.onDraw(Canvas )獲取的 Canvas 的繪圖區(qū)域(坐標系)確是 View 的。Canvas 在哪里做的變換呢?

onDraw(Canvas) 是在 draw(Canvas) 方法里被調(diào)用的,但是 Draw 方法里也沒有看到 Canvas 做變換的代碼。

通過 Studio 分析源碼,父 View 調(diào)用 drawChild 的時候直接就跳到了子 View 的 Draw 方法里。Canvas 是在哪里做變換的?!

draw 的 “錯誤跳轉(zhuǎn)”

寫了一個 LinearLayoutDebug 類,在 dispatchDraw 時打印 canvas width 和 height 屬性:

?打印 drawChild 時 canvas 的尺寸

再寫了一個 ViewDebug 類,在 draw(Canvas)時打印 Canvas width 和 height屬性:

打印 draw 時 canvas 的尺寸

打印結(jié)果是這樣:

canvas 尺寸的 “突變”

Canvas 的 size 出現(xiàn)了 “突變”!真邪門!

不信邪,打斷點看看,怎么 drawChild 下一步到 Draw,Canvas 直接就做了變換。

斷點不知怎么跳的,因為看到的代碼不是 draw(Canvas),所以重新審視 Studio 的代碼自動跳轉(zhuǎn)。

再看,原來是 Studio 跳錯地方了!

再看一遍 gif,ViewGroup 調(diào)用的是 child.draw(Canvas,ViewGroup,long),但 Studio 卻跳到了 Draw(Canvas)去,Draw(Canvas,ViewGroup,long)被 Studio 省略了!

draw 的 ”錯誤跳轉(zhuǎn)“

draw(Canvas,ViewGroup,long)

分析這個被 Studio “忽略” 了的方法,可以看到里面出現(xiàn)了 Matrix,canvas.translate 等代碼。draw(Canvas)也在 draw(Canvas,ViewGroup,long)里被調(diào)用。

結(jié)論

ViewGroup 傳給子 View 的是自己的 Canvas,子 View 在draw(Canvas,ViewGroup,long)方法里對 Canvas 做 了合適的變換,使 Canvas 的尺寸,坐標系等與子 View 自身的尺寸,位置相匹配。

View 在 draw(Canvas)里調(diào)用 drawBackground,onDraw,dispatchDraw 等方法完成自身的繪制。draw(Canvas)的 Canvas 已經(jīng)做了合適的變換,我們在重寫onDraw,dispatchDraw 等方法時不需要做變換。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容