HenCoder Android UI 部分 2-1 佈局基礎
HenCoder 的第二季:自定義 View 第二部分——佈局過程的自定義,從這期正式開始了。好像有點小激動。
廢話少說,直入正題。
簡介
之前我說過,自定義 View 最關鍵的有三個點:繪製、佈局和觸控反饋。上一季講過的繪製,內容雖然多(好像講了 8 期?),但難度上其實是最簡單的。而佈局就和它相反,佈局過程的技術知識,內容比較少(應該 3 期就能講完),但你先要理解它的內部工作原理才能正確理解它的使用,而它的工作原理卻是有點繞的。所以如果你跟著 HenCoder 學習佈局過程的自定義,大致會是這樣一種體驗:看完視訊或者讀完文章,感覺吸收了一大波知識,資訊量好大難以吞嚥的樣子,但當你真的把它們吞嚥下去,然後下載了我的練習專案去做練習的時候,卻又發現:臥槽,就這麼點東西?佈局過程的自定義竟然這麼簡單?
會者不難這個詞在很多地方都講得通,但在佈局過程的自定義上,尤為適用。
具體的概念、原理和技術細節,來看視訊吧:
總結
有人說:什麼?簡介完了就是總結了?
嚯嚯,對的。所有的內容都在視訊裡講完了,所以在這裡就把視訊裡講到的關鍵點總結一下:
佈局過程的含義
佈局過程,就是程式在執行時利用佈局檔案的程式碼來計算出實際尺寸的過程。
佈局過程的工作內容
兩個階段:測量階段和佈局階段。
測量階段:從上到下遞迴地呼叫每個 View 或者 ViewGroup 的 measure() 方法,測量他們的尺寸並計算它們的位置; 佈局階段:從上到下遞迴地呼叫每個 View 或者 ViewGroup 的 layout() 方法,把測得的它們的尺寸和位置賦值給它們。
View 或 ViewGroup 的佈局過程
-
測量階段,
measure()
方法被父 View 呼叫,在measure()
中做一些準備和優化工作後,呼叫onMeasure()
來進行實際的自我測量。onMeasure()
做的事,View
和ViewGroup
不一樣:- View:
View
在onMeasure()
中會計算出自己的尺寸然後儲存; - ViewGroup:
ViewGroup
在onMeasure()
中會呼叫所有子 View 的measure()
讓它們進行自我測量,並根據子 View 計算出的期望尺寸來計算出它們的實際尺寸和位置(實際上 99.99% 的父 View 都會使用子 View 給出的期望尺寸來作為實際尺寸,原因在下期或下下期會講到)然後儲存。同時,它也會根據子 View 的尺寸和位置來計算出自己的尺寸然後儲存;
- View:
-
佈局階段,
layout()
方法被父 View 呼叫,在layout()
中它會儲存父 View 傳進來的自己的位置和尺寸,並且呼叫onLayout()
來進行實際的內部佈局。onLayout()
做的事,View
和ViewGroup
也不一樣:- View:由於沒有子 View,所以
View
的onLayout()
什麼也不做。 - ViewGroup:
ViewGroup
在onLayout()
中會呼叫自己的所有子 View 的layout()
方法,把它們的尺寸和位置傳給它們,讓它們完成自我的內部佈局。
- View:由於沒有子 View,所以
佈局過程自定義的方式
三類:
- 重寫
onMeasure()
來修改已有的View
的尺寸; - 重寫
onMeasure()
來全新定製自定義View
的尺寸; - 重寫
onMeasure()
和onLayout()
來全新定製自定義ViewGroup
的內部佈局。
第一類自定義的具體做法
也就是重寫 onMeasure()
來修改已有的 View
的尺寸的具體做法:
- 重寫
onMeasure()
方法,並在裡面呼叫super.onMeasure()
,觸發原有的自我測量; - 在
super.onMeasure()
的下面用getMeasuredWidth()
和getMeasuredHeight()
來獲取到之前的測量結果,並使用自己的演算法,根據測量結果計算出新的結果; - 呼叫
setMeasuredDimension()
來儲存新的結果。