[Unity] Unity新UI系統(tǒng)概述Auto Layout

Rect Transform擁有的布局系統(tǒng)對于各種類型的布局是足夠靈活的,并且它也可以讓你自由放置元素。但是,有時(shí)候更多結(jié)構(gòu)化的東西是需要的。

自動(dòng)布局系統(tǒng)提供了在嵌套布局組(如水平組、豎直組或者格子組)中放置元素的方法。它還允許元素根據(jù)包含的內(nèi)容量自動(dòng)調(diào)整大小。例如,一個(gè)按鈕可以根據(jù)文本的內(nèi)容自動(dòng)縮放大小。

自動(dòng)布局系統(tǒng)是一個(gè)構(gòu)造在基本Rect Transform布局系統(tǒng)之上的系統(tǒng)。它可以選擇性的對一些或全部元素使用。

理解布局元素

自動(dòng)布局系統(tǒng)是基layout elements(布局元素)和layout controllers(布局控制器)的。布局元素是一個(gè)含有RectTransform組件和其它可選組件的游戲?qū)ο蟆helayout element has certain knowledge about which size it should have.布局元素不能直接設(shè)置自己的大小,但是其它作為布局控制器的組件可以使用它們提供的信息用來為它們計(jì)算尺寸。

一個(gè)布局元素用下列屬性來定義自身:

Minimun width(最小寬度)

Minimum height(最小高度)

Preferred width(首選寬度)

Preferred height(首選高度)

Flexible width(靈活寬度)

Flexible height(靈活高度)

使用布局元素提供信息的布局控制器的例子是Content Size Fitter和各種Layout Group組件。在布局組中如何按大小來布局元素的基本原則如下:

最開始只分配最小尺寸;

如果有足夠的空間,分配首選尺寸;

如果有額外的空間,分配靈活尺寸;

含有RectTransform組件的任何游戲?qū)ο蠖伎梢宰鳛椴季衷厥褂?。默認(rèn)它們的最小、首選和靈活尺寸都是0。某些組件添加到游戲?qū)ο笊虾髸?huì)改變這些布局屬性值。

Image和Text組件就是兩個(gè)會(huì)提供布局元素屬性值的例子。它們會(huì)改變首選寬度和高度以匹配精靈或者文本內(nèi)容。

Layout Element組件

如果你想覆蓋最小、首選或者靈活尺寸,你可以通過為游戲?qū)ο筇砑右粋€(gè)Layout Element組件來完成。


Layout Element組件可以讓你覆蓋一個(gè)或多個(gè)布局屬性值。勾選對應(yīng)控件,然后指定你需要覆蓋的數(shù)值。

請參看Layout Element參考文檔獲取更多的信息。

理解布局控制器

布局控制器一些是用來控制一個(gè)或多個(gè)布局元素尺寸和位置的組件,它也含有Rect Trasnform組件。一個(gè)布局控制器可能控制它的own layout element(自己所在的同一個(gè)對象)或者控制child layout elements。

Content Size Fitter(內(nèi)容尺寸適應(yīng)器)

Content Size Fitter用于控制自身布局元素的尺寸。查看自動(dòng)布局系統(tǒng)執(zhí)行方式的最簡單方法就是增加一個(gè)Content Size Fitter組件到含有Text組件的游戲?qū)ο笊稀?/p>


如果你將Horizontal Fit或Vertical Fit設(shè)置為Preferred Size,Rect Transform組件就會(huì)自動(dòng)調(diào)整它的寬或高以適應(yīng)文本呢內(nèi)容。

請參看Content Size Fitter相關(guān)參考文檔。

Aspect Ratio Fitter(縱橫比適應(yīng)器)

Aspcet Ratio Fitter用于控制自身布局元素的尺寸。


它可以讓高度適應(yīng)寬度,反之亦然,也可以讓元素放在父對象的內(nèi)部或者包裹父對象。Aspcet Ratio Fitter不會(huì)考慮最小尺寸和首選尺寸等布局信息。

請參看Aspect Ratio Fitter相關(guān)參考文檔。

Layout Group(布局組)

Layout Group是用來控制子布局元素的大小和位置的控制器。例如,水平的布局組將它的子對象相鄰的放置,而格子布局組將它的子對象放在格子里。

布局組不能控制自己的大小。但可以作為一個(gè)布局元素被其它控制器控制或者手動(dòng)設(shè)置。

不管布局組如何分配尺寸,大多數(shù)時(shí)候它都是試圖用每一個(gè)子布局元素設(shè)置的minimum,preferred和flexible尺寸來分配適當(dāng)數(shù)量的空間。布局組也可以任意嵌套。

請參看Horizontal Layout Group, Vertical Layout Group和Gird LayoutGroup相關(guān)的參考文檔。

驅(qū)動(dòng)Rect Transform屬性

因?yàn)樽詣?dòng)布局系統(tǒng)中的布局控制器會(huì)自動(dòng)控制那些不能通過觀察窗口或者場景窗口同時(shí)進(jìn)行手動(dòng)編輯的UI元素的尺寸和位置。而且這些被改變的值在下一次布局計(jì)算時(shí)會(huì)將被重新設(shè)置。

為了解決這個(gè)問題,Rect Transform有一個(gè)driven properties(被驅(qū)動(dòng)屬性)的概念。比如,將HorizontalFit屬性設(shè)置到Minimum或者Preferred的Content Size Fitter組件會(huì)驅(qū)動(dòng)同對象上Rect Transform組件的寬度。這個(gè)寬度值變?yōu)橹蛔x并且在Rect Transform的頂端會(huì)出現(xiàn)一個(gè)小的信息框告知一個(gè)或多個(gè)屬性值被content Size Fitter驅(qū)動(dòng)。

Rect Transform屬性被驅(qū)動(dòng)除了避免手動(dòng)編輯之外還有其它原因。僅僅是通過改變分辨率或者游戲窗口大小就會(huì)引起布局的改變。這反過來會(huì)改變布局元素的尺寸和位置,也就會(huì)改變被驅(qū)動(dòng)屬性的值。但是并不希望僅僅因?yàn)楦淖兞擞螒虼翱诘拇笮【蜁?huì)造成場景被標(biāo)記為未被保存狀態(tài)。為了避免這個(gè)問題,被驅(qū)動(dòng)屬性的值不會(huì)和場景一起保存并且他們的改變也不會(huì)引起場景數(shù)據(jù)的改變。

自動(dòng)布局系統(tǒng)伴隨著會(huì)使用一些內(nèi)建的組件,但是它也可能用自定義的方式創(chuàng)建出新的組件來控制布局。這是通過能被自動(dòng)布局系統(tǒng)的特殊組件接口來實(shí)現(xiàn)的。

如果執(zhí)行了ILayoutElement接口,組件就會(huì)被自動(dòng)布局系統(tǒng)當(dāng)作一個(gè)布局元素來對待。

如果執(zhí)行了ILayoutGroup接口,組件就會(huì)驅(qū)動(dòng)子對象的RectTransform。

如果執(zhí)行了ILayoutSelfController接口,組件就去驅(qū)動(dòng)自身的Rect Transform。

自動(dòng)布局系統(tǒng)會(huì)按下面的步驟計(jì)算并執(zhí)行布局:

1. 通過調(diào)用ILayoutElement組件上的CalculateLayoutInputHorizontal接口計(jì)算最小,首選和靈活的寬度。這是按從自下而上的順序,即子對象比父對象先執(zhí)行,這樣的話,父對象才能拿到子對象的數(shù)據(jù)以便進(jìn)行自身的計(jì)算;

2. 布局元素的有效寬度被ILayoutController組件上的SetLaytouHorizontal接口計(jì)算并設(shè)置。這是自上而下進(jìn)行的,即子對象在父對象之后計(jì)算,因?yàn)樽訉ο蟮姆峙湫枰鶕?jù)父對象完整的可用寬度來決定。這一步之后,布局元素的Rect Transform會(huì)擁有新的寬度;

3. 計(jì)算高度的最小,首選和靈活值,計(jì)算方法和第1步類似,只是接口為CalculateLaytouInputVertical;

4. 計(jì)算高度的有效值,計(jì)算方法和第2步類似,只是接口為SetLaytouVertical。

觸發(fā)布局的重建

當(dāng)組件上的一個(gè)屬性改變后,會(huì)導(dǎo)致當(dāng)前的布局不再有效,就需要做一個(gè)布局的重計(jì)算。者會(huì)被這個(gè)調(diào)用觸發(fā):

LayoutRebuilder.MarkLayoutForRebuild(transformas RectTransform);

這個(gè)重建不會(huì)立即發(fā)生,而是等到這幀的末尾,也就是渲染之前。不立即執(zhí)行的理由是因?yàn)樗鼤?huì)導(dǎo)致在同一幀內(nèi)地進(jìn)行多次潛在的布局重建,這會(huì)導(dǎo)致性能下降。

RectTransform刷新不及時(shí)的解決辦法:

http://www.tuicool.com/articles/AnQv2yB

http://www.xuanyusong.com/archives/4234

會(huì)觸發(fā)重建的時(shí)機(jī)為:

會(huì)改變布局的屬性設(shè)置器(setters);

這些回調(diào)函數(shù)種:

???OnEnable

???OnDisable

???OnRectRansformDimensionsChange

???OnValidate(只有編輯器狀態(tài)需要,運(yùn)行時(shí)不用)

???OnDidApplyAnimationProperties

unity的LayoutGroup分為三種, Horizontal Layout Group(水平布局)Vertical Layout Group(垂直布局)Grid Layout Group (網(wǎng)格布局) 以前NGUI沒有這東西都是自己寫工具實(shí)現(xiàn)的。為什么我們要布局?我舉個(gè)例子,布局的時(shí)候可以兩個(gè)cell 和三個(gè)cell都居中顯示。如下圖所示。。



尤其在獎(jiǎng)勵(lì)窗口,因?yàn)楂@取道具的數(shù)量是不固定的,所以需要根據(jù)不同數(shù)量的道具來居中對齊。如下圖所示,Padding 就是偏移,因?yàn)槲业腸ell 是 95X95,為了居中所以這里設(shè)置成 right = -95 top = -95。

Spacing 表示 cell之間的距離。

Child Alignment 表示對齊方式。

Child Force Expand 表示 自適應(yīng) 寬 和高


在看看cell,注意Layout Group節(jié)點(diǎn)下面的所有cell節(jié)點(diǎn)都是不能修改Rect Transform的。因?yàn)閏ell可能下面會(huì)放很多圖片,這樣我們會(huì)用個(gè)空的gameObject來當(dāng)父節(jié)點(diǎn)。但是這個(gè)gameObject的width 和 height 是最小單位,那么Layout Group就不知道怎么來算居中了。如下圖所示?這個(gè)時(shí)候就輪到LayoutElement登場了, 用它來設(shè)置一個(gè)cell的最大或者最小寬度。


如果運(yùn)行時(shí)實(shí)例化后的gameObject 直接放在 Layout Group下面即可。Layout Group會(huì)自動(dòng)計(jì)算布局,真的是非常方便。

for(int?i?=0?;i?<10;i++){

GameObject?go?=?(GameObject)Instantiate(Resources.Load<GameObject>(“item”));

go.transform.parent?=?transform;

go.transform.localScale?=?Vector3.one;

}

還有個(gè)問題就是隱藏,比如把其中的一個(gè)cell setActive = false ,為了不計(jì)算隱藏的cell 所以要先把 IngonreLaytout = true 再 setActivity?= false? 這一切都可以在代碼里面來設(shè)置。


代碼這樣即可。

gameObject.GetComponent<LayoutElement>().ignoreLayout?=?true;

gameObject.SetActive(false);

在unity3D4.6中加入了新的Transform 系統(tǒng)”Rect?Transform”。新的Rect?Transform對應(yīng)的是以前舊版本的“?Transform??2D”。在這里不過多的介紹Rect?Transform,今后我會(huì)在之后的文章中講解到新的Rect?Transform。

用過Rect?Transform的人都知道,Rect?Transform中rect的Widh/Health并不能Set,于是這樣就導(dǎo)致了Widh/Health不能動(dòng)態(tài)的修改。這里我給大家提供一個(gè)方法,通過添加Aspect Ratio Fitter/Content Size Fitter組件,來實(shí)現(xiàn)Widh/Health的動(dòng)態(tài)變化。

Aspect Ratio Fitter

Aspect Mode以什么樣的模式去調(diào)整矩形的縱橫比。

None不使用適合的縱橫比。

Width Controls Height讓Height隨著width自動(dòng)調(diào)節(jié)

Height Controls Width讓width隨著Height自動(dòng)調(diào)節(jié)

Fit In Parent寬度,高度,位置和錨點(diǎn)被自動(dòng)調(diào)整,以使該矩形擬合父物體的矩形內(nèi),同時(shí)保持高寬比。該可以是不包括在本RECT父矩形里面的一些空間。

Envelope Parent寬度,高度,位置和錨被自動(dòng)調(diào)整,以使該矩形覆蓋父的整個(gè)區(qū)域,同時(shí)保持高寬比。此矩形可能進(jìn)一步延伸出,使他比父物體正確。

Aspect Ratio寬高比來執(zhí)行。這是寬度除以身高。

Content Size Fitter

Horizontal Fit用什么樣的方法來控制寬度

None不使用任何基于布局元素的寬度。

Minimum使用基于布局元素的最小寬度的寬度。

Preferred使用基于布局元件的優(yōu)選寬度的寬度。

Vertical Fit用什么樣的方法來控制高度

None不使用任何基于布局元素的高度。

Minimum使用基于布局元素的最小高度的高度。

Preferred使用基于布局元件的優(yōu)選高度的高度。

我個(gè)人比較習(xí)慣用Content Size Fitter,只要管理好子物體的元素布局與大小就可以很好的控制Widh/Health。當(dāng)然,在使用過程中,根據(jù)具體情況來選擇適合的方法來實(shí)現(xiàn)動(dòng)態(tài)的調(diào)整Widh/Health。

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

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

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