本文分享Unity中的自動布局(AutoLayout)
在大部分情況下, Unity提供的RectTransform已經足夠應付我們日常遇到的需求, 我們一般通過手動修改RectTransform即可.
但是在有些情況下, 我們需要動態設定RectTransform, 特別是動態調整大小或者一些組合布局的需求.
Unity給我們提供了滿足這種需求的機制, 就是所謂自動布局.
自動布局的基本介紹
自動布局由兩部分組成, 即布局元素(LayoutElements)和布局控制器(LayoutControllers).
布局元素本身并不會對RectTransform做任何修改, 需要由布局控制器來根據自身的性質和布局元素的值來設定.
布局控制器分為控制自身的和控制子節點兩類.
不管是自身還是子節點, 被控制器控制之后無法手動修改RectTransform, 有些是不能修改位置, 有些是不能修改大小, 視具體的控制器而定, 如圖被控制了位置和高度:

如果父節點同時擁有控制自身的和控制子節點的控制器, 因為此時子節點由父節點控制, 所以子節點不能擁有控制自身的控制器:

布局元素(LayoutElement)
布局元素指實作了介面ILayoutElement的組件或者擁有布局元素的物件.
如果擁有多個布局元素組件, 根據layoutPriority確定優先級, 比如Image為0, InputField為1, 同時存在時, 會優先使用InputField的屬性.
布局元素相關的組件有:

屬性說明
布局元素實作介面后, 將會擁有以下屬性, 并在屬性面板最下方通過切頁顯示, 并在屬性面板最下方通過切頁顯示:




說明
Min Width/Height: 最小大小Preferred Width/Height: 首選大小, 根據元素內容得到的最適合大小Flexible Width/Height: 靈活大小, 相對單位大小, 默認情況下不啟用LayoutElement組件: 默認情況下布局元素會自動調節屬性, 如果不滿意可以通過添加LayoutElement組件手動調節IgnoreLayout: 忽略自動布局, 將當前布局元素宣告為非布局元素, 忽略自動布局的影響Layout Priority:同一個元素可以添加多個LayoutElement組件, 根據此屬性可以調節組件之間的優先級, 值越大優先級越高
布局控制器(LayoutControllers)
布局控制器是指實作了介面ILayoutController的類, 類圖如下

控制器的分類
控制器根據控制的物件可以分為控制自身和控制子節點的型別.
控制自身大小和位置(RectTransforms)
實作了ILayoutSelfController介面的類:
AspectRatioFitter: 寬高比配接器, 根據Aspect Mode屬性選擇適當的模式來適配自身的大小, 忽略布局元素的值.ContentSizeFitter: 內容大小配接器, 使用布局元素的最大/最小值或者偏好大小來確定自身的大小.- 可以指定水平或者垂直方向上的適配方式來控制寬度和高度
Horizontal Fit/Vertical FitNone: 不控制Minimum: 根據布局元素的最小值Preferred: 根據布局元素的偏好值
控制子節點大小和位置(RectTransforms)
實作了ILayoutGroup介面的類:
-
GridLayoutGroup: 網格布局, 子節點被稱為Cell, Cell大小和位置固定由空間驅動, Cell的LayoutElement無效 -
水平布局或者垂直布局: 此類控制器默認只能控制子節點的位置, 如果需要根據子節點的布局元素類控制需要設定
Child Controls SizeHorizontalLayoutGroup: 水平布局VerticalLayoutGroup: 垂直布局- 屬性說明
Child Alignment: 確定子節點的排序Child Controls Size: 通過子節點的布局元素來確定子節點的大小- Child Force Expand: 如何處理父節點的剩余部分
Child Controls Size勾選時(這里子節點針對布局元素, 決定位置和大小): 在滿足各個子節點的PreferredSize后, 剩余的部分Size由各個子節點填充, 填充如下- 將所有子節點的
FlexibleSize加起來為TotalFlexibleSize, 如果子節點沒有設定FlexibleSize, 那么默認為1 - 剩余的部分Size除以TotalFlexibleSize獲得平均FlexibleSize的大小
- 子節點根據自身
FlexibleSize乘以平均FlexibleSize的大小獲得填充大小
- 將所有子節點的
Child Controls Size未勾選時(這里子節點針對所有RectTransform元素, 決定位置): 按照所有的子節點RectTransform的大小排列之后, 多余的部分當做間隔平分填充到子節點之間
使用示例
下面給出兩個比較常見的需求, 作為上述理論的實踐.
(1)Text內容自適應
需求說明: 默認情況下Text的大小需要手動指定, 我們想要固定寬度或者高度, 讓另一個方向根據內容自動調整.
Text實作了ILayoutElemtent介面, 是一個布局元素, 默認情況下:
Min Width/Height為0Flexible Widht/Height不生效- 根據當前內容和當前
RectTransform的值計算適合的PreferredSize - 此時布局元素的屬性不影響
RectTransform 

添加控制器ContentSizeFitter, 調節自身大小為首選大小:


(2)由子節點大小動態確定父節點的大小
需求: 某些情況下, 一些容器型別的物件, 我們希望其大小是根據子節點大小動態變化的, 比如ScrollView的Content動態擴容.
解決思路: Content需要控制自身大小, 也需要控制子節點大小:
- 控制子節點大小: 根據子節點的布局元素屬性來設定子節點大小(首選和最小都可以)
- 控制自身大小: 子節點的大小設定完成后, Content的首選大小會被正確的設定, 之后我們可以使用
ContentSizeFitter來選擇首選大小控制自己的大小即可
具體步驟演示:
-
構建垂直方向上的
ScrollView:

-
添加VerticalLayoutGroup并設定控制子節點
ChildControlsSize:Height


- 此時子節點的首選大小和如果小于
Content的大小, 那么所有的子節點平分Content的大小 - 此時子節點的首選大小和如果大于
Content的大小, 那么所有的子節點按照首選大小來設定, 剩余的部分根據是否設定FlexibleSize來處理 - 上圖
Content的大小與首選大小不匹配, 當前的大小超過了首選大小, 并不是最適合的
- 此時子節點的首選大小和如果小于
-
添加
ContentSizeFitter控制自身大小, 此時Content的高度與首選高度一致, 是所有子節點(布局元素)的高度之和


轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/336600.html
標籤:其他
