NGUI所見(jiàn)即所得之UIGrid & UITable
By D.S.Qiu
尊重他人的勞動(dòng),支持原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:http.dsqiu.iteye.com
你是不是對(duì) UIGrid 和 UITable 定位計(jì)算方法還模糊不清,那么這篇文章就是你需要的。
NGUI 提供了 Grid 和 Table 組件,支持的參數(shù)很少,功能也很雞肋,完全不能像 CSS 的 Box 模型那樣隨心所欲的布局,而且使用 UIGrid 和 UITable 的時(shí)候經(jīng)常會(huì)相對(duì) UIGrid 和 UITable 掛載的 Transform 出現(xiàn)偏移,之前使用的時(shí)候,都是根據(jù)經(jīng)驗(yàn)來(lái)規(guī)避的。今天打算把UIGrid 和 UITable 的排列規(guī)則看下, 才形成此文。
UIGrid 和 UITable 的原理很簡(jiǎn)單,對(duì)子 Transform 的 List 進(jìn)行排序,然后更加不同的規(guī)則進(jìn)行定位排列(UIGrid 和 UITable 還是有很大不同的)。
排序(Sort)
UIGrid 和 UITable 定義了5種排列方式(其實(shí)是3種,None默認(rèn)不排序即Transform的默認(rèn)排序,Custom雖然提供virtual 可以重載):
對(duì)應(yīng)的三種排序方法:集 Alphabetic 按照名字字符串排序,Horizontal 和 Vertical 按照l(shuí)ocalPosition 進(jìn)行的排序
這里說(shuō)下,雖然提供了Custom方式,第一感覺(jué)NGUI的developer考慮很周到,但是提供的確實(shí)重載 virtual 函數(shù)的方式,D.S.Qiu 覺(jué)得這種方式太不好了,為了一個(gè)方法就要寫(xiě)一個(gè) 子類(lèi)去重載,個(gè)人覺(jué)得指定一個(gè)委托,擴(kuò)展起來(lái)會(huì)更直觀,但這一要求開(kāi)發(fā)者一開(kāi)始就得指定這個(gè) Custom Sort Delegate。
UIGrid定位原理
下面這段代碼是 Reposition() 的一部分,原理很簡(jiǎn)單:根據(jù)定義的cellHeight 和cellWidth 來(lái)調(diào)整子 Transform 的 localPosition。這里還是吐槽下:Reposition() 的代碼太多容易了,至少我看到了這段代碼在 Reposition 中出現(xiàn)了兩次,完全多余,其實(shí)就是處理流程就應(yīng)該是: 先獲取所有子 Transform List ,然后對(duì)List 排序,最后就是下面這段定位代碼了。
UITable 定位原理
UITable 的定位方法在 ReositionVaribleSize 中,跟UIGrid 最大不同點(diǎn)是:UIGrid 只根據(jù)定義的cellHeight 和 cellWidth 來(lái)計(jì)算位置,UITable 根據(jù)“內(nèi)容“(UIWidget)來(lái)計(jì)算位置的。
這里還是有吐槽:根據(jù) Bounds 的定義 b.extens.x - b.center.x + b.min.x == 0 ,也就是這部完全是沒(méi)有必要的,看來(lái)UIGrid 的 developer,不光代碼邏輯不清晰,難道連大腦都是豆腐花做的么。
類(lèi)似計(jì)算 y 的值也其他更直接方法:
使用經(jīng)驗(yàn)
1.UIGrid 沒(méi)有考慮Bounds ,根據(jù)UIGrid 的計(jì)算公式可以知道:UIGrid 的第一個(gè)元素的 localPosition 的 x 和 y 一定都是 0 ,所以要位置,必須調(diào)整UIGrid 的localPosition ,但是實(shí)際在有可能調(diào)整的是 子對(duì)象,然后再 Scene 窗口看是沒(méi)問(wèn)題的(注意此時(shí)還沒(méi)有重排),一運(yùn)行就會(huì)出現(xiàn)位置的偏移。
2.UITable 的子組件的 x 總是以 每列最左為 起始基準(zhǔn)點(diǎn)的, y 則是每行居中對(duì)齊 :(b.max.y - b.min.y - bc.max.y + bc.min.y) * 0.5f 這行代碼起始就是計(jì)算當(dāng)前組件和所在行中心點(diǎn)的偏移。
下圖是將NGUI 其中一個(gè)組件的 sprite 左移了,就出現(xiàn)下面的排列:
雖然 NGUI 提供了 UIGrid 和 UITable ,起始是非常之不完善,幾乎做不了什么功能。這里分享兩條經(jīng)驗(yàn):
1.使用UIGrid時(shí),調(diào)整界面的時(shí)候讓 UIGrid 的 transform 和 其第一個(gè)子組件的 transform 相同,這樣經(jīng)過(guò)計(jì)算之后,位置就是之前調(diào)整想要的?;蛘邔?第一個(gè)子組件 transform 重置,這樣調(diào)整UIGrid 的 transform 位置看到的效果就是真實(shí)的。
2.使用UITable 讓每列元素的左邊界都相同,即左對(duì)齊??梢钥吹?NGUI Example 的 Question Log 的 Table 的所有組件(UILable UISprite)的 pivot 都調(diào)整為 left 。
總之,就是根據(jù)UIGrid 和UITable 的排列原理做相應(yīng)的調(diào)整。
小結(jié):
這篇文章相對(duì)于NGUI所見(jiàn)即所得系列其他文章來(lái)說(shuō),簡(jiǎn)單很多。最近要做一個(gè)界面根據(jù)內(nèi)容自適應(yīng),挺復(fù)雜的,一堆莫名其妙的問(wèn)題。之前一直覺(jué)得 Unity 的 UI 沒(méi)有Window MFC 等開(kāi)發(fā)直接拖拽方式那么直觀。NGUI 雖然很龐大,但NGUI越來(lái)越容易讓我吐槽了,可能是對(duì)NGUI的家底多少掌握的緣故吧。
很久就聽(tīng)說(shuō)Unity要出自己的 UI 了,其實(shí)D.S.Qiu 也一直有想嘗試自己寫(xiě)一點(diǎn)UI的可視化編輯工具(Visual Editor)。昨天不經(jīng)意看到 Cocos2D 的 UI 編輯器 CocoStudio 感覺(jué)很強(qiáng)大,然后順手google Unity有沒(méi)有這方面的工具,果然還是發(fā)現(xiàn)了 UIToolkit , bitverse RagePixel 和 EWS editor ,也就說(shuō) Unity其實(shí)也有些 UI 可視化工具的。尤其 bitverse 支持的組件特別豐富,很強(qiáng)大,只可惜沒(méi)有集成 Batch DrawCall 的功能。
如果您對(duì)D.S.Qiu有任何建議或意見(jiàn)可以在文章后面評(píng)論,或者發(fā)郵件(gd.s.qiu@gmail.com)交流,您的鼓勵(lì)和支持是我前進(jìn)的動(dòng)力,希望能有更多更好的分享。
轉(zhuǎn)載請(qǐng)?jiān)谖氖鬃⒚鞒鎏帲?a style="line-height: 1.5;" >http://dsqiu.iteye.com/blog/2034883
更多精彩請(qǐng)關(guān)注D.S.Qiu的博客和微博(ID:靜水逐風(fēng))
聯(lián)系客服