1. 程式人生 > >HenCoder Android UI 部分 2-1 佈局基礎

HenCoder Android UI 部分 2-1 佈局基礎

HenCoder 的第二季:自定義 View 第二部分——佈局過程的自定義,從這期正式開始了。好像有點小激動。

廢話少說,直入正題。

簡介

之前我說過,自定義 View 最關鍵的有三個點:繪製、佈局和觸控反饋。上一季講過的繪製,內容雖然多(好像講了 8 期?),但難度上其實是最簡單的。而佈局就和它相反,佈局過程的技術知識,內容比較少(應該 3 期就能講完),但你先要理解它的內部工作原理才能正確理解它的使用,而它的工作原理卻是有點繞的。所以如果你跟著 HenCoder 學習佈局過程的自定義,大致會是這樣一種體驗:看完視訊或者讀完文章,感覺吸收了一大波知識,資訊量好大難以吞嚥的樣子,但當你真的把它們吞嚥下去,然後下載了我的練習專案去做練習的時候,卻又發現:臥槽,就這麼點東西?佈局過程的自定義竟然這麼簡單?

會者不難這個詞在很多地方都講得通,但在佈局過程的自定義上,尤為適用。

具體的概念、原理和技術細節,來看視訊吧:

總結

有人說:什麼?簡介完了就是總結了?

嚯嚯,對的。所有的內容都在視訊裡講完了,所以在這裡就把視訊裡講到的關鍵點總結一下:

佈局過程的含義

佈局過程,就是程式在執行時利用佈局檔案的程式碼來計算出實際尺寸的過程。

佈局過程的工作內容

兩個階段:測量階段和佈局階段。

測量階段:從上到下遞迴地呼叫每個 View 或者 ViewGroup 的 measure() 方法,測量他們的尺寸並計算它們的位置; 佈局階段:從上到下遞迴地呼叫每個 View 或者 ViewGroup 的 layout() 方法,把測得的它們的尺寸和位置賦值給它們。

View 或 ViewGroup 的佈局過程

  1. 測量階段,measure() 方法被父 View 呼叫,在 measure() 中做一些準備和優化工作後,呼叫 onMeasure() 來進行實際的自我測量。 onMeasure() 做的事,View 和 ViewGroup 不一樣:

    1. ViewView 在 onMeasure() 中會計算出自己的尺寸然後儲存;
    2. ViewGroupViewGroup 在 onMeasure() 中會呼叫所有子 View 的 measure() 讓它們進行自我測量,並根據子 View 計算出的期望尺寸來計算出它們的實際尺寸和位置(實際上 99.99% 的父 View 都會使用子 View 給出的期望尺寸來作為實際尺寸,原因在下期或下下期會講到)然後儲存。同時,它也會根據子 View 的尺寸和位置來計算出自己的尺寸然後儲存;
  2. 佈局階段,layout() 方法被父 View 呼叫,在 layout() 中它會儲存父 View 傳進來的自己的位置和尺寸,並且呼叫 onLayout() 來進行實際的內部佈局。onLayout() 做的事, View 和 ViewGroup 也不一樣:

    1. View:由於沒有子 View,所以 View 的 onLayout() 什麼也不做。
    2. ViewGroupViewGroup 在 onLayout() 中會呼叫自己的所有子 View 的 layout() 方法,把它們的尺寸和位置傳給它們,讓它們完成自我的內部佈局。

佈局過程自定義的方式

三類:

  1. 重寫 onMeasure() 來修改已有的 View 的尺寸;
  2. 重寫 onMeasure() 來全新定製自定義 View 的尺寸;
  3. 重寫 onMeasure() 和 onLayout() 來全新定製自定義 ViewGroup 的內部佈局。

第一類自定義的具體做法

也就是重寫 onMeasure() 來修改已有的 View 的尺寸的具體做法:

  1. 重寫 onMeasure() 方法,並在裡面呼叫 super.onMeasure(),觸發原有的自我測量;
  2. 在 super.onMeasure() 的下面用 getMeasuredWidth() 和 getMeasuredHeight() 來獲取到之前的測量結果,並使用自己的演算法,根據測量結果計算出新的結果;
  3. 呼叫 setMeasuredDimension() 來儲存新的結果。