Author Topic: UIWrapContent with multiple columns  (Read 8913 times)

davitosan

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 9
    • View Profile
UIWrapContent with multiple columns
« on: June 28, 2016, 04:22:12 PM »
Unity 5.3.4p4
NGUI 3.9.4

I've read through these:
http://www.tasharen.com/forum/index.php?topic=10160.0 - Topic: How to use UIWrapContent programatically?
http://www.tasharen.com/forum/index.php?topic=10245.0 -  Topic: Fast scrolling Grid [add and remove row dynamically]

I have a similar requirement as the posters above.
-An undefined 'n' size of items to be scrolled within a pool of Drag Scroll Views.

Unfortunately my design requires 2 and sometimes 3 columns in my vertical scrollview.

I'm confused as to if UIWrapContent supports that. Can it be used with Table or Grid?

davitosan

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 9
    • View Profile
Re: UIWrapContent with multiple columns
« Reply #1 on: June 28, 2016, 05:43:51 PM »
This is the solution I've come up with that doesn't use UIWrapContent.
There seems to be some error when we are at the moment we need to reposition the scrollview, sometimes it get's stuck and needs an extra nudge from user input; sometimes the next row doesn't populate for a cell.

+Root (Managing Script)
|-UIScrollBar
|-UIPanel+UIScrollView(Unreferenced ScrollBars)
|--UITable(Columns: 2, Direction: Down, Pivot: Top Left)
|---UIDragScrollView
|---UIDragScrollView
|---UIDragScrollView
...


Here is code. Two vars are located in a different class:
-TopCellIndex: is an int specifying the top cell being shown by the scrollview
-data: is a list of all the objects this scrollview will be scrolling through.

  1. public class MultiColumnWrap : MonoBehaviour
  2. {
  3.         [Header("Prefabs")]
  4.         public GameObject CellPrefab;
  5.  
  6.         [Header("NGUI Scrolling")]
  7.         public UIPanel _UIPanel;
  8.         public UIScrollView _scrollView;
  9.         public UITable _table;
  10.         public UIScrollBar _scrollBar;
  11.  
  12.         private List<CellScript> _cellList;
  13.         private GameObject _lastCell
  14.  
  15.         private int _numCellsInPanel;   //This is how many cells the panel can fit
  16.         private Vector2 _cellSize;
  17.         private float _svStartingPosY;
  18.  
  19.         void Start()
  20.         {
  21.                 //Instantiate enough Prefabs to fill our Panel and then some. This will be our cycling pool of Cells
  22.                 _cellList = new List<CellScript>();
  23.  
  24.                 //Get Bounds of the prefabs that will populate this view
  25.                 GameObject template = NGUITools.AddChild(_table.gameObject, CellPrefab);
  26.                 Bounds b = NGUIMath.CalculateRelativeWidgetBounds(template.transform, true);
  27.                 GameObject.Destroy(template);
  28.  
  29.                 //Calculate the maximum number of cells a user could see within the panel
  30.                 _cellSize.x = b.size.x;
  31.                 _cellSize.y = b.size.y;
  32.  
  33.                 //Calculate how many cells we can fit in the panels clip region
  34.                 _numCellsInPanel = Mathf.CeilToInt(_UIPanel.baseClipRegion.w / (_cellSize.y + _table.padding.y)) * _table.columns;
  35.                 //Add one more row to cover scrolling
  36.                 _numCellsInPanel += Mathf.FloorToInt(_UIPanel.baseClipRegion.z / (_cellSize.x + _table.padding.x));
  37.                 //Instantiate cells and make them inactive
  38.                 for(int i = 0; i < _numCellsInPanel; i++)
  39.                 {
  40.                         GameObject cellGO = NGUITools.AddChild(_table.gameObject, CellPrefab);
  41.                         CellScript cellScript = cellGO.GetComponent<CellScript>();
  42.                         if(cellScript != null)
  43.                         {
  44.                                 _cellList.Add(cellScript);
  45.                         }
  46.                         cellGO.SetActive(false);
  47.                 }
  48.  
  49.                 //Set the Cells with our Data
  50.                 for(int i = TopCellIndex, j = 0; i < data.Length && j < _numCellsInPanel; i++, j++)
  51.                 {
  52.                         CellScript cellScript = _cellList[j].GetComponent<CellScript>();
  53.                         if(cellScript != null)
  54.                         {
  55.                                 _lastCell = cellScript[i];
  56.  
  57.                                 cellScript.gameObject.SetActive(true);
  58.                                 cellScript.SetData(data[i]);
  59.                         }
  60.                 }
  61.  
  62.                 _table.repositionNow = true;
  63.                 _scrollView.ResetPosition();
  64.  
  65.                 //Start our update loop
  66.                 StartCoroutine(UpdateCR());
  67.         }
  68.  
  69.         IEnumerator UpdateCR()
  70.         {
  71.                 yield return null; //Wait for NGUI to Reposition
  72.  
  73.                 _svStartingPosY = _scrollView.transform.localPosition.y;
  74.  
  75.                 //let's spin our main loop
  76.                 while(true)
  77.                 {
  78.                         //Make sure we aren't already showing the bottom cell
  79.                         if(_lastCell != data[data.Length - 1])
  80.                         {
  81.                                 //Check if we moved a row off screen - Down
  82.                                 if(_scrollView.transform.localPosition.y > (_svStartingPosY + _cellSize.y))
  83.                                 {
  84.                                         MoveScrollView(true);
  85.                                 }
  86.                         }
  87.                         else
  88.                         {
  89.                                 _scrollView.RestrictWithinBounds(true);
  90.                         }
  91.  
  92.                         //Make sure we aren't already showing the top cell
  93.                         if(TopCellIndex > 0)
  94.                         {
  95.                                 //Check if we moved a row off screen - Up
  96.                                 if(_scrollView.transform.localPosition.y < _svStartingPosY)
  97.                                 {
  98.                                         MoveScrollView(false);
  99.                                 }
  100.                         }
  101.                         else
  102.                         {
  103.                                 _scrollView.RestrictWithinBounds(true);
  104.                         }
  105.  
  106.                         UpdateScrollbar();
  107.  
  108.                         yield return null;//tick
  109.                 }
  110.         }
  111.  
  112.         void MoveScrollView(bool moveDown)
  113.         {
  114.                 if(moveDown == true)
  115.                 {
  116.                         TopCellIndex += _table.columns;
  117.                 }
  118.                 else
  119.                 {
  120.                         TopCellIndex -= _table.columns;
  121.                 }
  122.  
  123.                 Mathf.Clamp(TopCellIndex, 0, data.Length);
  124.  
  125.                 for(int i = 0; i < _cellList.Count; i++)
  126.                 {
  127.                         CellScript currCell = _cellList[i];
  128.                         if(TopCellIndex + i >= data.Length)
  129.                         {
  130.                                 //We've run out of players on the data side
  131.                                 currCell.gameObject.SetActive(false);
  132.                         }
  133.                         else
  134.                         {
  135.                                 //Set the data, and update
  136.                                 currCell.gameObject.SetActive(true);
  137.  
  138.                                 _lastCell = data[TopCellIndex + i];
  139.  
  140.                                 currCell.SetData(_lastCell);
  141.                         }
  142.                 }
  143.  
  144.                 float distance = _cellSize.y;
  145.                 _scrollView.MoveRelative(new Vector3(0.0f, moveDown ? -distance : distance, 0.0f));
  146.         }
  147.  
  148.         void UpdateScrollbar()
  149.         {
  150.                 if(data.Length < _numCellsInPanel)
  151.                 {
  152.                         _scrollBar.gameObject.SetActive(false);
  153.                 }
  154.                 else if(data.Length > 0)
  155.                 {
  156.                         _scrollBar.gameObject.SetActive(true);
  157.  
  158.                         float pct = TopCellIndex / (float)(data.Length - _numCellsInPanel);
  159.                         _scrollBar.value = Mathf.Lerp(_scrollBar.value, pct, 0.1f);
  160.                         _scrollBar.barSize = _numCellsInPanel / (float)data.Length;
  161.                 }
  162.         }
  163. }
  164.  
« Last Edit: June 28, 2016, 06:23:00 PM by davitosan »

davitosan

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 9
    • View Profile
Re: UIWrapContent with multiple columns
« Reply #2 on: June 29, 2016, 10:30:26 PM »
I've came across this forum post
http://www.tasharen.com/forum/index.php?topic=8936.0 - Runtime dynamic scrollview

In it, ArenMook gives the advice:
Quote
If you need multiple rows, then organize your content like this:

UIWrapContent
- Row 1 (UIGrid)
-- Item 1
-- Item 2
-- Item 3
- Row 2 (UIGrid)
-- Item 4
-- Item 5
-- Item 6

I'm attempting to do so with Example 14 - Vertical 3. This is how I've set it up, looks fine before playing. I made sure the UIPanel is wide enough.


but, after pressing play, the UIGrid objects are placed on the same x (column), and for some reason the first grid is placed down one height (-100). I haven't been able to figure out how to get the two columns.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIWrapContent with multiple columns
« Reply #3 on: July 01, 2016, 10:28:53 PM »
Every game object underneath the UIWrapContent object is a single item. The advice you used has rows, not columns. 3 items per row to be precise. In your case you want 2 items per row, but you set it up as 2 items with 5 children each for some reason. Instead you should have had 5 items with 2 children each.