国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

NGUI所見即所得之UIGrid & UITable

2019-11-09 17:33:14
字體:
供稿:網(wǎng)友

尊重他人的勞動,支持原創(chuàng),轉(zhuǎn)載請注明出處:http.dsqiu.iteye.com

 

       你是不是對 UIGrid 和 UITable 定位計算方法還模糊不清,那么這篇文章就是你需要的。

       NGUI 提供了 Grid 和 Table 組件,支持的參數(shù)很少,功能也很雞肋,完全不能像 CSS 的 Box 模型那樣隨心所欲的布局,而且使用 UIGrid 和 UITable 的時候經(jīng)常會相對 UIGrid 和 UITable 掛載的 Transform 出現(xiàn)偏移,之前使用的時候,都是根據(jù)經(jīng)驗來規(guī)避的。今天打算把UIGrid 和 UITable 的排列規(guī)則看下, 才形成此文。

 

        UIGrid 和 UITable 的原理很簡單,對子 Transform 的 List 進行排序,然后更加不同的規(guī)則進行定位排列(UIGrid 和 UITable 還是有很大不同的)。

 

排序(Sort)

        UIGrid 和 UITable 定義了5種排列方式(其實是3種,None默認不排序即Transform的默認排序,Custom雖然提供virtual 可以重載):

C#代碼  收藏代碼public enum Sorting  {      None,      Alphabetic,      Horizontal,      Vertical,      Custom,  }  

         對應(yīng)的三種排序方法:集 Alphabetic 按照名字字符串排序,Horizontal 和 Vertical 按照localPosition 進行的排序

C#代碼  收藏代碼static public int SortByName (Transform a, Transform b) { return string.Compare(a.name, b.name); }  static public int SortHorizontal (Transform a, Transform b) { return a.localPosition.x.CompareTo(b.localPosition.x); }  static public int SortVertical (Transform a, Transform b) { return b.localPosition.y.CompareTo(a.localPosition.y); }  

         這里說下,雖然提供了Custom方式,第一感覺NGUI的developer考慮很周到,但是提供的確實重載 virtual 函數(shù)的方式,D.S.Qiu 覺得這種方式太不好了,為了一個方法就要寫一個 子類去重載,個人覺得指定一個委托,擴展起來會更直觀,但這一要求開發(fā)者一開始就得指定這個 Custom Sort Delegate。

 

UIGrid定位原理

        下面這段代碼是 Reposition() 的一部分,原理很簡單:根據(jù)定義的cellHeight 和cellWidth 來調(diào)整子 Transform 的 localPosition。這里還是吐槽下:Reposition() 的代碼太多容易了,至少我看到了這段代碼在 Reposition 中出現(xiàn)了兩次,完全多余,其實就是處理流程就應(yīng)該是: 先獲取所有子 Transform List ,然后對List 排序,最后就是下面這段定位代碼了。

C#代碼  收藏代碼for (int i = 0, imax = list.Count; i < imax; ++i)  {      Transform t = list[i];      if (!NGUITools.GetActive(t.gameObject) && hideInactive) continue;      float depth = t.localPosition.z;      Vector3 pos = (arrangement == Arrangement.Horizontal) ?          new Vector3(cellWidth * x, -cellHeight * y, depth) :          new Vector3(cellWidth * y, -cellHeight * x, depth);        if (animateSmoothly && application.isPlaying)      {          SPRingPosition.Begin(t.gameObject, pos, 15f).updateScrollView = true;      }      else t.localPosition = pos;        if (++x >= maxPerLine && maxPerLine > 0)      {          x = 0;          ++y;      }  }  

 

UITable 定位原理

       UITable 的定位方法在 ReositionVaribleSize 中,跟UIGrid 最大不同點是:UIGrid 只根據(jù)定義的cellHeight 和 cellWidth 來計算位置,UITable 根據(jù)“內(nèi)容“(UIWidget)來計算位置的。

C#代碼  收藏代碼protected void RepositionVariableSize (List<Transform> children)  {      float xOffset = 0;      float yOffset = 0;        int cols = columns > 0 ? children.Count / columns + 1 : 1;      int rows = columns > 0 ? columns : children.Count;        Bounds[,] bounds = new Bounds[cols, rows];      Bounds[] boundsRows = new Bounds[rows];      Bounds[] boundsCols = new Bounds[cols];        int x = 0;      int y = 0;          //這個循環(huán)計算每行,每列,每個cell 的內(nèi)容的編輯 Bounds      for (int i = 0, imax = children.Count; i < imax; ++i)      {          Transform t = children[i];          Bounds b = NGUIMath.CalculateRelativeWidgetBounds(t, !hideInactive);            Vector3 scale = t.localScale;          b.min = Vector3.Scale(b.min, scale);          b.max = Vector3.Scale(b.max, scale);          bounds[y, x] = b;            boundsRows[x].Encapsulate(b);          boundsCols[y].Encapsulate(b);            if (++x >= columns && columns > 0)          {              x = 0;              ++y;          }      }        x = 0;      y = 0;          //計算位置      for (int i = 0, imax = children.Count; i < imax; ++i)      {          Transform t = children[i];          Bounds b = bounds[y, x];          Bounds br = boundsRows[x];          Bounds bc = boundsCols[y];            Vector3 pos = t.localPosition;          pos.x = xOffset + b.extents.x - b.center.x;          pos.x += b.min.x - br.min.x + padding.x;   //以每列最右邊的x值為標準,即保證每列最左邊的基準點            if (direction == Direction.Down)          {              pos.y = -yOffset - b.extents.y - b.center.y;              pos.y += (b.max.y - b.min.y - bc.max.y + bc.min.y) * 0.5f - padding.y;          }          else          {              pos.y = yOffset + (b.extents.y - b.center.y);              pos.y -= (b.max.y - b.min.y - bc.max.y + bc.min.y) * 0.5f - padding.y;          }            xOffset += br.max.x - br.min.x + padding.x * 2f;            t.localPosition = pos;            if (++x >= columns && columns > 0)          {              x = 0;              ++y;                xOffset = 0f;              yOffset += bc.size.y + padding.y * 2f;          }      }  }  

          這里還是有吐槽:根據(jù) Bounds 的定義 b.extens.x - b.center.x + b.min.x == 0 ,也就是這部完全是沒有必要的,看來UIGrid 的 developer,不光代碼邏輯不清晰,難道連大腦都是豆腐花做的么。

C#代碼  收藏代碼pos.x = xOffset + b.extents.x - b.center.x;  pos.x += b.min.x - br.min.x + padding.x;  

           類似計算 y 的值也其他更直接方法:

C#代碼  收藏代碼(b.max.y - b.min.y - bc.max.y + bc.min.y) * 0.5f  

 

使用經(jīng)驗

      1.UIGrid 沒有考慮Bounds ,根據(jù)UIGrid 的計算公式可以知道:UIGrid 的第一個元素的 localPosition 的 x 和 y 一定都是 0 ,所以要位置,必須調(diào)整UIGrid 的localPosition ,但是實際在有可能調(diào)整的是 子對象,然后再 Scene 窗口看是沒問題的(注意此時還沒有重排),一運行就會出現(xiàn)位置的偏移。

      2.UITable 的子組件的 x 總是以 每列最左為 起始基準點的, y 則是每行居中對齊 :(b.max.y - b.min.y - bc.max.y + bc.min.y) * 0.5f 這行代碼起始就是計算當前組件和所在行中心點的偏移。

   下圖是將NGUI 其中一個組件的 sprite 左移了,就出現(xiàn)下面的排列:

 

       雖然 NGUI 提供了 UIGrid 和 UITable ,起始是非常之不完善,幾乎做不了什么功能。這里分享兩條經(jīng)驗:

               1.使用UIGrid時,調(diào)整界面的時候讓 UIGrid 的 transform 和 其第一個子組件的 transform 相同,這樣經(jīng)過計算之后,位置就是之前調(diào)整想要的。或者將 第一個子組件 transform 重置,這樣調(diào)整UIGrid 的              transform 位置看到的效果就是真實的。

               2.使用UITable 讓每列元素的左邊界都相同,即左對齊。可以看到 NGUI Example 的 Question Log 的 Table 的所有組件(UILable UISprite)的 pivot 都調(diào)整為 left 。

 

        總之,就是根據(jù)UIGrid 和UITable 的排列原理做相應(yīng)的調(diào)整。

 

 

小結(jié):

       這篇文章相對于NGUI所見即所得系列其他文章來說,簡單很多。最近要做一個界面根據(jù)內(nèi)容自適應(yīng),挺復(fù)雜的,一堆莫名其妙的問題。之前一直覺得 Unity 的 UI 沒有Window MFC 等開發(fā)直接拖拽方式那么直觀。NGUI 雖然很龐大,但NGUI越來越容易讓我吐槽了,可能是對NGUI的家底多少掌握的緣故吧。

        很久就聽說Unity要出自己的 UI 了,其實D.S.Qiu 也一直有想嘗試自己寫一點UI的可視化編輯工具(Visual Editor)。昨天不經(jīng)意看到 Cocos2D 的 UI 編輯器 CocoStudio 感覺很強大,然后順手google Unity有沒有這方面的工具,果然還是發(fā)現(xiàn)了 UIToolkit , bitverse RagePixel 和 EWS editor ,也就說 Unity其實也有些 UI 可視化工具的。尤其 bitverse 支持的組件特別豐富,很強大,只可惜沒有集成 Batch  DrawCall 的功能。

 

       如果您對D.S.Qiu有任何建議或意見可以在文章后面評論,或者發(fā)郵件(gd.s.qiu@Gmail.com)交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。

       轉(zhuǎn)載請在文首注明出處:http://dsqiu.iteye.com/blog/2034883


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 阳高县| 永年县| 和龙市| 延安市| 卢龙县| 安龙县| 嘉义县| 封开县| 平泉县| 馆陶县| 交口县| 漳浦县| 清苑县| 阜平县| 宝应县| 睢宁县| 房产| 福州市| 阿克苏市| 剑川县| 泸西县| 山丹县| 馆陶县| 永康市| 桑植县| 青神县| 汽车| 泸水县| 栾川县| 陆河县| 长岭县| 永靖县| 抚顺市| 平山县| 尼玛县| 尼玛县| 巫山县| 福泉市| 丰城市| 博爱县| 鄂托克前旗|