• NGUI布局组件:UIGrid /UITable


    一、UIGrid:排列等比大小子对象。
    Reposition:排列方法。
    1. 触发:MonoBehaviour的Start、设置repositionNow= true或者手动调用。
    1. 获取并排列子对象:GetChildList,排序方法也很简单。
    public List<Transform> GetChildList ()
    {
       Transform myTrans = transform;
       List<Transform> list = new List<Transform>();
     
       for (int i = 0; i < myTrans.childCount; ++i)
       {
          Transform t = myTrans.GetChild(i);
     
          if (!hideInactive || (t && t.gameObject.activeSelf))
          {
             if (!UIDragDropItem.IsDragged(t.gameObject)) list.Add(t);
          }
       }
     
       // Sort the list using the desired sorting logic
       if (sorting != Sorting.None && arrangement != Arrangement.CellSnap)
       {
          if (sorting == Sorting.Alphabetic) list.Sort(SortByName);
          else if (sorting == Sorting.Horizontal) list.Sort(SortHorizontal);
          else if (sorting == Sorting.Vertical) list.Sort(SortVertical);
          else if (onCustomSort != null) list.Sort(onCustomSort);
          else Sort(list);
       }
       return list;
    }
     
    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); }
    1. 按左上角为起始点排序子节点。
    int x = 0;
    int y = 0;
    int maxX = 0;
    int maxY = 0;
     
    // Re-add the children in the same order we have them in and position them accordingly
    for (int i = 0, imax = list.Count; i < imax; ++i)
    {
       Transform t = list[i];
       Vector3 pos = t.localPosition;
       float depth = pos.z;
     
       if (arrangement == Arrangement.CellSnap)
       {
          if (cellWidth > 0) pos.x = Mathf.Round(pos.x / cellWidth) * cellWidth;
          if (cellHeight > 0) pos.y = Mathf.Round(pos.y / cellHeight) * cellHeight;
       }
       else pos = (arrangement == Arrangement.Horizontal) ?
          new Vector3(cellWidth * x, -cellHeight * y, depth) : //横向排序,x轴递增cellWidth
          new Vector3(cellWidth * y, -cellHeight * x, depth); //纵向排序,y轴递减cellHeight
     
       if (animateSmoothly && Application.isPlaying && (pivot != UIWidget.Pivot.TopLeft || Vector3.SqrMagnitude(t.localPosition - pos) >= 0.0001f))
       {
          var sp = SpringPosition.Begin(t.gameObject, pos, 15f);
          sp.updateScrollView = true;
          sp.ignoreTimeScale = true;
       }
       else t.localPosition = pos;
     
       maxX = Mathf.Max(maxX, x);//最大列数
       maxY = Mathf.Max(maxY, y);//最大行数
     
       if (++x >= maxPerLine && maxPerLine > 0) //换行
       {
          x = 0;
          ++y;
       }
    }
    • 执行结果如下:
    1. 通过pivot调整相对与父节点的坐标,因为父节点坐标不变,实际是变相整体位移了所有子节点。
    • 上图的po是(0,0),下图是(0.5, 0.5)。
    if (pivot != UIWidget.Pivot.TopLeft)
    {
       var po = NGUIMath.GetPivotOffset(pivot);
     
       float fx, fy;
     
       if (arrangement == Arrangement.Horizontal)
       {
          fx = Mathf.Lerp(0f, maxX * cellWidth, po.x);
          fy = Mathf.Lerp(-maxY * cellHeight, 0f, po.y);
       }
       else
       {
          fx = Mathf.Lerp(0f, maxY * cellWidth, po.x);
          fy = Mathf.Lerp(-maxX * cellHeight, 0f, po.y);
       }
     
       foreach (var t in list)
       {
          Vector3 pos = t.localPosition;
             pos.x -= fx;
             pos.y -= fy;
             t.localPosition = pos;
       }
    }
     
    二、UITable:排列不同大小的子对象,会计算子节点的包围盒。
    Reposition:排列方法。
    1. 触发:MonoBehaviour的Start、设置repositionNow= true(在lateUpdate执行,也就是当前帧结束时)或者手动调用。
    1. 获取并排列子对象:GetChildList,排序方法调的是UIGrid的接口。
    1. 子节点、每行、每列的包围盒计算,注意这边的包围盒center都是(0,0),第y行的的包围盒boundsCols[y]实际上是center(0,0),extents.x = 改行节点最大的宽/2,extents.y = 改行节点最大的高/2。bounds[y, x]一定是包含在范围更大的boundsRows[x]、boundsCols[y]内,且中心点都在(0,0)点。
    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;
       }
    }
    • 如上图,b.size=b.extents*2,min = -b.extents,max = b.extents.
    1. 以左上角为基点,排列子节点。看注释段比较好理解。
    Vector2 po = NGUIMath.GetPivotOffset(cellAlignment);
     
    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 -= Mathf.Lerp(0f, b.max.x - b.min.x - br.max.x + br.min.x, po.x) - padding.x;
     
       //pos.x = xOffset + b.extents.x;//x现在在左边界
       //float maxDis = (br.max.x - br.min.x) - (b.max.x - b.min.x);
       //loat offsetX  = Mathf.Lerp(0f, maxDis, po.x) ;//计算最终要偏移的距离
       //pos.x += offsetX  +  padding.x;
     
       if (direction == Direction.Down)
       {
          pos.y = -yOffset - b.extents.y - b.center.y;
          pos.y += Mathf.Lerp(b.max.y - b.min.y - bc.max.y + bc.min.y, 0f, po.y) - padding.y;
       }
       else
       {
          pos.y = yOffset + b.extents.y - b.center.y;
          pos.y -= Mathf.Lerp(0f, b.max.y - b.min.y - bc.max.y + bc.min.y, po.y) - padding.y;
       }
     
       xOffset += br.size.x + padding.x * 2f;
     
       t.localPosition = pos;
     
       if (++x >= columns && columns > 0)
       {
          x = 0;
          ++y;
     
          xOffset = 0f;
          yOffset += bc.size.y + padding.y * 2f;
       }
    }
    • 先把子节点放在当前列br的左边界。pos.x = xOffset + b.extents.x;
    • 计算从左边界移到当前列br有边界的距离。float maxDis = (br.max.x - br.min.x) - (b.max.x - b.min.x);
    • 通过cellAlignment计算最终要偏移的距离。float offsetX  = Mathf.Lerp(0f, maxDis, po.x) ;
    • 修正pos。pos.x += offsetX  +  padding.x
    左上角对齐:
    右下对齐:
    1. 通过pivot调整相对与父节点的坐标,因为父节点坐标不变,实际是变相修改了子节点的坐标。同UIGride.
  • 相关阅读:
    红黑树-插入篇
    并查集
    Rabin-Karp【转载】
    KMP
    怎样花两月时间去应聘互联网公司 [转载]
    c++ 智能指针【转载】
    java序列化
    Web页面导出Excel表格
    基于jquery-UI的日期选择器
    Doc命令
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/13509107.html
Copyright © 2020-2023  润新知