Skip to main content
special

Unity UGUI 原理篇(五):Auto Layout 自動佈局

目標

  • Auto Layout System 架構
  • Layout Element 元素大小
  • Horizontal、Vertical 、Grid Layout Group 元素排列
  • Content Size 與 Aspect Ratio Fitter 大小控制

 

本系列其他文章

 

使用環境 與 版本

  • Window 7
  • Unity 5.2.4

 

Auto Layout System

Auto Layout System 是基於 Rect Transform Layout System 之上的系統,自動調整一個或多個的元素大小、位置、間格,又分為 Layout Controllers(父物件) 與 Layout Elements(子物件) 兩部分,一個簡單的 Auto Layout 架構如下 (此處介紹理論,實作留到後面)

AutoLayoutSystem_01

 

 

Layout Element (子物件)

代表著每個元素的大小,擁有資訊如下:

Minimum Width

最小寬度

Minimum Height

Preferred Width

優先寬度

Preferred Height

Flexible Width

彈性寬度

Flexible Height

 

點選UI後,可以在 Inspector 最下方切換為 Layout Properties 看到資訊

LayoutElement_05

LayoutElement_03

 

Layout Controllers 透過不同的佈局方式,取得 Layout Element size 分配子物件,基本原則如下

  • 首先分配 Minimum Size
  • 如果還有足夠空間,分配 Preferred Size
  • 如果還有額外空間,分配 Flexible Size

 

從以下圖片可以看出圖片寬度的增長方式 (此處介紹理論,實作留到後面)

LayoutElement_01

LayoutElement_02

  • 首先分配 Minimum Size (300,紅色部分)
  • 如果還有足夠空間,分配 Preferred Size (300~500,綠色部分)
  • 如果還有額外空間,分配 Flexible Size:1 (500~700,藍色部分)

 

比較特別的是 Flexible,他是代表著整個大小的比例,如果 Layout 下有2個物體,分別給 Flexible 設定為 0.3 與 0.7,那比例就會變成下圖 (3:7)

LayoutElement_04

另外要注意的是,TextImage Component 會根據內容大小自動分配 Preferred Size

 

Layout Controllers (父物件)

Layout Group

不會控制 Layout Controllers (父物件)自身大小,而是控制子物件大小與位置,在大多數情況下,根據每個元素的 minimum、preferred、flexible 大小分配適當的空間,layout group 之間也可以嵌套,又分為 Horizontal(水平)Vertical(垂直)Grid(格狀) 3種

 

Horizontal Layout Group

HorizontalLayoutGroup_00

水平方向(Width) 排列子物件

組件位置:Unity Menu Item → Component → Layout → Horizontal Layout Group

  • Padding:填充內部空間
  • Spacing:每個元素間格
  • Child Alignment:當沒有填滿全部空間時,子物件對齊位置
  • Child Force Expand:強制控制子物件填滿空間

 

透過實例理解各參數:

A. 開新 Scene
Unity Menu Item → File → New Scene

B. 新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas

C. Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)

D. 父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group

E. 父物件下建立5個 Button(子物件),完成後如下,當大小改變時會自動分配子物件大小

HorizontalLayoutGroup_02

 

F. 此時在 Button 的 Rect Transform Component 就不能進行調整,因為我們已經透過 Horizontal Layout Group 進行分配空間,在 Rect Transform 會顯示目前被哪個 Layout Group 控制

HorizontalLayoutGroup_09

 

G. 將 Padding 數值調整如圖,可以看出填充區域

HorizontalLayoutGroup_03

 

H. 將 Spacing 數值調整如圖,可以看出元素區間

HorizontalLayoutGroup_04

 

I. 接下來我們將5個 Button 增加 Layout Element Component 覆蓋預設大小,用於手動設定每個元素的大小
組件位置:Unity Menu Item → Component → Layout → Layout Element

J. 此時將 Horizontal Layout Group 的 Child Force Expand Width 取消勾選,不強制子物件填滿額外空間,而是透過 Layout Element 手動設定

K. 這裡使用幾種不同的設定,來理解 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件

■ 複習一下子物件大小分配方式

  • 首先分配 Minimum Size
  • 如果還有足夠空間,分配 Preferred Size
  • 如果還有額外空間,分配 Flexible Size

 

■ 將5個 Button 的 Layout Element Min Width 分別改為 20、30、40、50、60,此時可以看出每個 Button 寬度分佈,改變父物件大小時子物件大小並不會改變,因為只有分配 Min Width,並不會分配額外有效空間

HorizontalLayoutGroup_11

 

此時改變 Horizontal Layout Group 的 Child Alignment,可以看出元素對齊

HorizontalLayoutGroup_16

 

父物件 Layout Properties Min Width = 5個按鈕寬(20+30+40+50+60=200) + Spacing(40) + Padding Left、Right(20) = 260

HorizontalLayoutGroup_10

 

■ 現在將第1個 Button 的 Layout Element 數值調整如圖

HorizontalLayoutGroup_13

這邊設定 Preferred Width 為 100

  1. 首先分配 Minimum Size(20)
  2. 空間足夠的情況下,將會分配剩下的 Preferred Size (20~100 空間),如下所示

HorizontalLayoutGroup_12

 

■ 現在將第1個 Button 的 Layout Element 數值調整如圖

HorizontalLayoutGroup_14

這邊設定 Flexible Width 為 1

  • 首先分配 Minimum Size(20)
  • 如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
  • 如果還有額外空間,分配剩下 Flexible Size,如下所示

HorizontalLayoutGroup_15

 

■ 現在將 Horizontal Layout Group 的 Child Force Expand Width 勾選,讓子物件強制填滿

  • 首先分配 Minimum Size(20)
  • 如果還有足夠空間,將會分配剩下的 Preferred Size (20~100 空間)
  • 如果還有額外空間,分配剩下元素 Flexible Size 與 Child Force Expand Width

HorizontalLayoutGroup_17

結論:
上面我們看到,所有元素會先被分配 Minimum Size,接下來還有足夠空間,將會分配剩下的 Preferred Size,最後才是 Flexible Size 與 Child Force Expand Width

至此我們了解到 Horizontal Layout Group 是怎麼取得 Layout Element size 分配子物件

 

Vertical Layout Group

VerticalLayoutGroup_00

垂直方向(Height) 排列子物件,與 Horizontal Layout Group 只差在水平或是垂直,這邊不在贅述

組件位置:Unity Menu Item → Component → Layout → Vertical Layout Group

 

Grid Layout Group

GridLayoutGroup_00

網格方式排列子物件

組件位置:Unity Menu Item → Component → Layout → Grid Layout Group

  • Padding:填充內部空間
  • Cell Size:每個元素的寬高

GridLayoutGroup_01

 

  • Spacing:每個元素間格
  • Start Corner:開始排列的角落(位置),又分為 “左上”、”右上”、”左下”、”右下”,請仔細看元素數字

GridLayoutGroup_02

 

  • Start Axis:”水平” 或是 “垂直” 排列,請仔細看元素數字

GridLayoutGroup_03

  • Child Alignment:當沒有填滿全部空間時,子物件對齊位置
  • Constraint:排列限制
    • Flexible:自動根據大小彈性排列
    • Fixed Column Count:限制排列 “行數(直)”
    • Fixed Row Count:限制排列 “列數(橫)”

 

Layout Fitter

控制著 Layout Controllers 自身大小,大小取決於子物件,或是設定的大小比例,又分為 Content Size Fitter 與 Aspect Ratio Fitter

Content Size Fitter

ContentSizeFitter_00

控制著 Layout Controllers (父物件)自身大小,大小取決於子物件的 Minimum 或是 Preferred 大小,能透過 Pivot 改變縮放方向

組件位置:Unity Menu Item → Component → Layout → Content Size Fitter

  • Horizontal、Vertical Fit:水平、垂直 適應調整
    • None 不調整
    • Min Size 根據子物件的 Minimum 大小進行調整
    • Preferred Size 根據子物件的 Preferred 大小進行調整

 

透過實例理解

如果我們現在有一個需求,必需要讓 “父物件大小” 根據 “子物件大小” 進行縮放,完成如下 (方便明顯看出父物件大小,增加黑色外框)

ContentSizeFitter_02

A. 開新 Scene
Unity Menu Item → File → New Scene

B. 新增一個 Canvas
Unity Menu Item → GameObject → UI → Canvas

C. Canvas 下新增空物件,做為 Layout Controllers (以下簡稱父物件)

D. 父物件增加 Horizontal Layout Group Component
Unity Menu Item → Component → Layout → Horizontal Layout Group

這時如果增加 Button(子物件),上面有提到,Horizontal Layout Group 會根據子物件的 Layout Element 進行分配子物件大小,而不會修改父物件本身的大小,如下所示 (方便明顯看出父物件大小,增加黑色外框)

ContentSizeFitter_01

E. 父物件下增加 Button(子物件),並增加 Layout Element Component 覆蓋預設大小,Minimum Width 調整為 100
組件位置:Unity Menu Item → Component → Layout → Layout Element

F. 父物件增加 Content Size Fitter Component,Horizontal Fit 調整為 Min Size,透過子物件 Minimum Width 調整父物件本身大小 (Horizontal 方向其實就是取得子物件 Width)

ContentSizeFitter_04

G. 此時如果 Button 複製增加,父物件本身的大小也會跟著改變,如下所示

ContentSizeFitter_02

H. 調整父物件的 pivot,可以控制縮放方向,如下所示

ContentSizeFitter_03

I. 通過上面實例,我們首先使用 Horizontal Layout Group 排列子物件,並在子物件增加 Layout Element 覆蓋預設大小,最後透過 Content Size Fitter 取得子物件 Layout Element 設定父物件大小,至此父物件大小就會根據子物件大小進行縮放

 

Aspect Ratio Fitter

AspectRatioFitter_00

控制著 Layout Controllers 自身大小,按照物件寬高比調整大小,能透過 pivot 改變縮放方向

組件位置:Unity Menu Item → Component → Layout → Aspect Ratio Fitter

Aspect Mode:調整模式

None:不調整

 

Width Controls Height

基於 Width 為基準,依據比例改變 Height

AspectRatioFitter_01_01

當 Width 改變時,Height 會依比例改變

AspectRatioFitter_01_02

 

Height Controls Width

基於 Height 為基準,依據比例改變 Width

AspectRatioFitter_02_01

當 Height 改變時,Width 會依比例改變

AspectRatioFitter_02_02

 

Fit In Parent

依據比例將 寬高、位置、anchors自動調整,使此圖形大小在父物件中完全貼齊,此模式可能不會包覆所有空間

調整比例 (方便明顯看出父物件增加黑底)

調整父物件大小,物體會依據比例貼齊父物件

AspectRatioFitter_03_02

 

Envelope Parent

依據比例將 寬高、位置、anchors自動調整,使此圖形大小完全包覆父物件,此模式可能會超出空間

調整比例 (方便明顯看出父物件增加黑框)

調整父物件大小,物體會依據比例包覆父物件

AspectRatioFitter_04_02

Aspect Ratio:比例,此數值為 寬/高

 

差別

Content Size Fitter 是透過子物件自動進行調整大小

Aspect Ratio Fitter 是透過數值(寬高比)進行調整

 

後記

Auto Layout System 可以快速、方便的排列多個 UI,當大小改變時會自動調整內容,也能應用在多層崁套下,在日後調整與修改上也是非常方便與直覺,是 UI 系統中必學的功能之一 !!

 

參考資料

 

歡迎轉載,並註明出處 !

 

Arkai

獨立遊戲開發、技術分享。 Indie Game development and technology sharing.

7 thoughts on “Unity UGUI 原理篇(五):Auto Layout 自動佈局

  1. 感謝大大的教學,讓小弟獲益良多,不過想請問一下大大

    我根據大大的教學在實作Horizontal Layout,我先建立了Panel並採用Horizontal Layout,然後將Child Force Expand的width打勾取消,接著加入三個Button在此Panel下,三個Button皆新增Layout Element,並皆有設定Min Width

    我看大大上述的教學,無論Panel拉大或拉小,Button都不會改變,且Button的Text並不會因為Button被拉大而模糊

    但為什麼我的Panel寬度拉大或拉小,Button的寬度皆會改變,並不會固定為所設定的Min Width,而且Button中的Text甚至會因為Button拉大而變得模糊

    如圖:http://imgur.com/a/43cx3

    謝謝

  2. 不好意思,我發現我把Panel拉大時,用到的是快捷鍵(R)來放大,所以改變的是Scale,應該要用快捷鍵(T)來改變大小才對,搞烏龍了,哈哈

什麼?不懂! 那就提問吧!