Search Unity

[Solved]How to make Grid Layout group Cell Size X Auto expand

Discussion in 'UGUI & TextMesh Pro' started by Collin_Patrick, Dec 29, 2016.

  1. Collin_Patrick

    Collin_Patrick

    Joined:
    Sep 24, 2016
    Posts:
    83
    I am trying to make a list of UI elements. I want there to always be 2 columns and a potentially infinite number of rows. I want each cell to expand their x size constraint to completely fill the allocated space without any empty space on the sides. How can I achieve this?

    This is what I want it to look like:
    What I want.PNG
    This is what I get upon changing resolutions:
    What I get.PNG
     
    DragonCoder, ToonLeaderBacon and ina like this.
  2. Collin_Patrick

    Collin_Patrick

    Joined:
    Sep 24, 2016
    Posts:
    83
    I found a small hack that let me do what I want. I took the source code of the grid layout group and changed a few lines to fit my needs.

    Found answer here:
    http://answers.unity3d.com/questions/989697/grid-layout-group-scalable-content.html

    Full script, just create a new script copy/paste the code and make sure it is named properly and id should work
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace UnityEngine.UI
    5. {
    6.     [AddComponentMenu("Layout/Auto Expand Grid Layout Group", 152)]
    7.     public class AutoExpandGridLayoutGroup : LayoutGroup
    8.     {
    9.         public enum Corner { UpperLeft = 0, UpperRight = 1, LowerLeft = 2, LowerRight = 3 }
    10.         public enum Axis { Horizontal = 0, Vertical = 1 }
    11.         public enum Constraint { Flexible = 0, FixedColumnCount = 1, FixedRowCount = 2 }
    12.  
    13.         [SerializeField]
    14.         protected Corner m_StartCorner = Corner.UpperLeft;
    15.         public Corner startCorner { get { return m_StartCorner; } set { SetProperty(ref m_StartCorner, value); } }
    16.  
    17.         [SerializeField]
    18.         protected Axis m_StartAxis = Axis.Horizontal;
    19.         public Axis startAxis { get { return m_StartAxis; } set { SetProperty(ref m_StartAxis, value); } }
    20.  
    21.         [SerializeField]
    22.         protected Vector2 m_CellSize = new Vector2(100, 100);
    23.         public Vector2 cellSize { get { return m_CellSize; } set { SetProperty(ref m_CellSize, value); } }
    24.  
    25.         [SerializeField]
    26.         protected Vector2 m_Spacing = Vector2.zero;
    27.         public Vector2 spacing { get { return m_Spacing; } set { SetProperty(ref m_Spacing, value); } }
    28.  
    29.         [SerializeField]
    30.         protected Constraint m_Constraint = Constraint.Flexible;
    31.         public Constraint constraint { get { return m_Constraint; } set { SetProperty(ref m_Constraint, value); } }
    32.  
    33.         [SerializeField]
    34.         protected int m_ConstraintCount = 2;
    35.         public int constraintCount { get { return m_ConstraintCount; } set { SetProperty(ref m_ConstraintCount, Mathf.Max(1, value)); } }
    36.  
    37.         protected AutoExpandGridLayoutGroup()
    38.         { }
    39.  
    40. #if UNITY_EDITOR
    41.         protected override void OnValidate()
    42.         {
    43.             base.OnValidate();
    44.             constraintCount = constraintCount;
    45.         }
    46. #endif
    47.  
    48.         public override void CalculateLayoutInputHorizontal()
    49.         {
    50.             base.CalculateLayoutInputHorizontal();
    51.  
    52.             int minColumns = 0;
    53.             int preferredColumns = 0;
    54.             if (m_Constraint == Constraint.FixedColumnCount)
    55.             {
    56.                 minColumns = preferredColumns = m_ConstraintCount;
    57.             }
    58.             else if (m_Constraint == Constraint.FixedRowCount)
    59.             {
    60.                 minColumns = preferredColumns = Mathf.CeilToInt(rectChildren.Count / (float)m_ConstraintCount - 0.001f);
    61.             }
    62.             else
    63.             {
    64.                 minColumns = 1;
    65.                 preferredColumns = Mathf.CeilToInt(Mathf.Sqrt(rectChildren.Count));
    66.             }
    67.  
    68.             SetLayoutInputForAxis(
    69.                 padding.horizontal + (cellSize.x + spacing.x) * minColumns - spacing.x,
    70.                 padding.horizontal + (cellSize.x + spacing.x) * preferredColumns - spacing.x,
    71.                 -1, 0);
    72.         }
    73.  
    74.         public override void CalculateLayoutInputVertical()
    75.         {
    76.             int minRows = 0;
    77.             if (m_Constraint == Constraint.FixedColumnCount)
    78.             {
    79.                 minRows = Mathf.CeilToInt(rectChildren.Count / (float)m_ConstraintCount - 0.001f);
    80.             }
    81.             else if (m_Constraint == Constraint.FixedRowCount)
    82.             {
    83.                 minRows = m_ConstraintCount;
    84.             }
    85.             else
    86.             {
    87.                 float width = rectTransform.rect.size.x;
    88.                 int cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x)));
    89.                 minRows = Mathf.CeilToInt(rectChildren.Count / (float)cellCountX);
    90.             }
    91.  
    92.             float minSpace = padding.vertical + (cellSize.y + spacing.y) * minRows - spacing.y;
    93.             SetLayoutInputForAxis(minSpace, minSpace, -1, 1);
    94.         }
    95.  
    96.         public override void SetLayoutHorizontal()
    97.         {
    98.             SetCellsAlongAxis(0);
    99.         }
    100.  
    101.         public override void SetLayoutVertical()
    102.         {
    103.             SetCellsAlongAxis(1);
    104.         }
    105.  
    106.         private void SetCellsAlongAxis(int axis)
    107.         {
    108.             // Normally a Layout Controller should only set horizontal values when invoked for the horizontal axis
    109.             // and only vertical values when invoked for the vertical axis.
    110.             // However, in this case we set both the horizontal and vertical position when invoked for the vertical axis.
    111.             // Since we only set the horizontal position and not the size, it shouldn't affect children's layout,
    112.             // and thus shouldn't break the rule that all horizontal layout must be calculated before all vertical layout.
    113.  
    114.             if (axis == 0)
    115.             {
    116.                 // Only set the sizes when invoked for horizontal axis, not the positions.
    117.                 for (int i = 0; i < rectChildren.Count; i++)
    118.                 {
    119.                     RectTransform rect = rectChildren[i];
    120.  
    121.                     m_Tracker.Add(this, rect,
    122.                         DrivenTransformProperties.Anchors |
    123.                         DrivenTransformProperties.AnchoredPosition |
    124.                         DrivenTransformProperties.SizeDelta);
    125.  
    126.                     rect.anchorMin = Vector2.up;
    127.                     rect.anchorMax = Vector2.up;
    128.                     rect.sizeDelta = cellSize;
    129.                 }
    130.                 return;
    131.             }
    132.  
    133.             float width = rectTransform.rect.size.x;
    134.             float height = rectTransform.rect.size.y;
    135.  
    136.             int cellCountX = 1;
    137.             int cellCountY = 1;
    138.             if (m_Constraint == Constraint.FixedColumnCount)
    139.             {
    140.                 cellCountX = m_ConstraintCount;
    141.                 cellCountY = Mathf.CeilToInt(rectChildren.Count / (float)cellCountX - 0.001f);
    142.             }
    143.             else if (m_Constraint == Constraint.FixedRowCount)
    144.             {
    145.                 cellCountY = m_ConstraintCount;
    146.                 cellCountX = Mathf.CeilToInt(rectChildren.Count / (float)cellCountY - 0.001f);
    147.             }
    148.             else
    149.             {
    150.                 if (cellSize.x + spacing.x <= 0)
    151.                     cellCountX = int.MaxValue;
    152.                 else
    153.                     cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x)));
    154.  
    155.                 if (cellSize.y + spacing.y <= 0)
    156.                     cellCountY = int.MaxValue;
    157.                 else
    158.                     cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y)));
    159.             }
    160.  
    161.             int cornerX = (int)startCorner % 2;
    162.             int cornerY = (int)startCorner / 2;
    163.  
    164.             int cellsPerMainAxis, actualCellCountX, actualCellCountY;
    165.             if (startAxis == Axis.Horizontal)
    166.             {
    167.                 cellsPerMainAxis = cellCountX;
    168.                 actualCellCountX = Mathf.Clamp(cellCountX, 1, rectChildren.Count);
    169.                 actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis));
    170.             }
    171.             else
    172.             {
    173.                 cellsPerMainAxis = cellCountY;
    174.                 actualCellCountY = Mathf.Clamp(cellCountY, 1, rectChildren.Count);
    175.                 actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis));
    176.             }
    177.  
    178.             Vector2 requiredSpace = new Vector2(
    179.                     actualCellCountX * cellSize.x + (actualCellCountX - 1) * spacing.x,
    180.                     actualCellCountY * cellSize.y + (actualCellCountY - 1) * spacing.y
    181.                     );
    182.             Vector2 startOffset = new Vector2(
    183.                     GetStartOffset(0, requiredSpace.x),
    184.                     GetStartOffset(1, requiredSpace.y)
    185.                     );
    186.  
    187.             for (int i = 0; i < rectChildren.Count; i++)
    188.             {
    189.                 int positionX;
    190.                 int positionY;
    191.                 if (startAxis == Axis.Horizontal)
    192.                 {
    193.                     positionX = i % cellsPerMainAxis;
    194.                     positionY = i / cellsPerMainAxis;
    195.                 }
    196.                 else
    197.                 {
    198.                     positionX = i / cellsPerMainAxis;
    199.                     positionY = i % cellsPerMainAxis;
    200.                 }
    201.  
    202.                 if (cornerX == 1)
    203.                     positionX = actualCellCountX - 1 - positionX;
    204.                 if (cornerY == 1)
    205.                     positionY = actualCellCountY - 1 - positionY;
    206.  
    207.                 float realsize = ((width - (spacing[0] * (actualCellCountX - 1))) / actualCellCountX);
    208.                 SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (realsize + spacing[0]) * positionX, realsize);
    209.                 SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
    210.             }
    211.         }
    212.     }
    213. }
     
  3. u-i

    u-i

    Joined:
    Nov 11, 2014
    Posts:
    5
    GREAT works just as i wanted! thx you
     
  4. Basic50

    Basic50

    Joined:
    Dec 30, 2013
    Posts:
    5
    Thank you so much! cellSize in read only... :( Great job Unity...
     
    ehsan_wwe1 and Menion-Leah like this.
  5. tredpro

    tredpro

    Joined:
    Nov 18, 2013
    Posts:
    515
    thanks for the code.

    added feature to choose between scaling on x, y, both, or none


    add enum

    Code (csharp):
    1.   public enum ExpandSetting { x, y, both, none };

    Code (csharp):
    1.   public ExpandSetting expandSetting;
    then replace

    Code (csharp):
    1.     float realsize = ((width - (spacing[0] * (actualCellCountX - 1))) / actualCellCountX);
    2.                 SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (realsize + spacing[0]) * positionX, realsize);
    3.                 SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
    4.             }
    5.         }
    6.  
    with

    Code (csharp):
    1.  
    2.  
    3.  
    4.  float realsizey;
    5.                 if (expandSetting == ExpandSetting.both)
    6.                 {
    7.                     if (rectChildren.Count != 1)
    8.                     {
    9.                         realsizey = ((height - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    10.                     }
    11.                     else
    12.                     {
    13.                         realsizey = ((height / constraintCount - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    14.  
    15.                     }
    16.  
    17.                     float realsize = ((width - (spacing[0] * (actualCellCountX - 1))) / actualCellCountX);
    18.                     SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (realsize + spacing[0]) * positionX, realsize);
    19.                     SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (realsizey + spacing[1]) * positionY, realsizey);
    20.  
    21.      
    22.                 }
    23.                 if (expandSetting == ExpandSetting.x)
    24.                 {
    25.              
    26.  
    27.                     float realsize = ((width - (spacing[0] * (actualCellCountX - 1))) / actualCellCountX);
    28.                     SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (realsize + spacing[0]) * positionX, realsize);
    29.                  
    30.                     SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
    31.  
    32.                 }
    33.                 if (expandSetting == ExpandSetting.y)
    34.                 {
    35.                     if (rectChildren.Count != 1)
    36.                     {
    37.                         realsizey = ((height - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    38.                     }
    39.                     else
    40.                     {
    41.                         realsizey = ((height / constraintCount - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    42.  
    43.                     }
    44.  
    45.                  
    46.                     SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (realsizey + spacing[1]) * positionY, realsizey);
    47.  
    48.                     SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
    49.            
    50.  
    51.                 }
    52.                 if (expandSetting == ExpandSetting.none)
    53.                 {
    54.                     SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
    55.                     SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
    56.                 }
    57.  
    58.  
    59.  
    60.  
     
    paperez97 and konradborowiecki like this.
  6. zyonneo

    zyonneo

    Joined:
    Apr 13, 2018
    Posts:
    386
    Hi ...i have done GridLayout using this AutoExpandGridLayoutGroup...Any idea on how to know which cell is clicked?So that I can perform certain action for that button click
     
  7. Grumpy-Dot

    Grumpy-Dot

    Joined:
    Feb 29, 2016
    Posts:
    93
    You can either add a button script to the cell elements OR add a custom script that implements the IPointerClickHandler interface and get the click event.
    The parent will have a collection (array/list) of the cell elements and add click listeners for all of them with a specific parameter to identify each cell.
    I can write some sample code if you are still confused about this.
     
    zyonneo likes this.
  8. zyonneo

    zyonneo

    Joined:
    Apr 13, 2018
    Posts:
    386
    I want to populate the Gridview with dynamic image buttons...which gets loaded from the data in the API.Sample code will be helpful,thanks..
     
  9. nbrindic

    nbrindic

    Joined:
    Mar 17, 2014
    Posts:
    7
    This script has small bug for vertical expansion of items. So, replace each occurence of:
    Code (csharp):
    1.  
    2. if (rectChildren.Count != 1)
    3. {
    4.     realsizey = ((height - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    5. }
    6. else
    7. {
    8.     realsizey = ((height / constraintCount - (spacing[0] * (actualCellCountY - 1))) / actualCellCountY);
    9. }
    10.  
    with:

    Code (csharp):
    1.  
    2. if (rectChildren.Count != 1)
    3. {
    4.     realsizey = ((height - (spacing[1] * (actualCellCountY - 1))) / actualCellCountY);
    5. }
    6. else
    7. {
    8.     realsizey = ((height / constraintCount - (spacing[1] * (actualCellCountY - 1))) / actualCellCountY);
    9. }
    10.  
    Basically, old script involved spacing[0] (X-spacing) in the equation for vertical (Y-spacing), so this fix just reverts spacing[0] to spacing[1] in the cases where Y-expansion should occur
     
    spinaLcord likes this.
  10. Aeridis

    Aeridis

    Joined:
    Apr 26, 2014
    Posts:
    1
    Padding from the bottom d the right don't work with this script, and padding from the top and the left pushes the cells outside the boundaries. How can I fix this?

    Also, is there a way to maintain an aspect ratio with the cells? For example if you have a 2:1 window with 1:1 cells in it. Is there a way to expand the cells to fit the window while maintaining it's shape?
     
    cemugurk likes this.
  11. Mathyx92

    Mathyx92

    Joined:
    Apr 9, 2019
    Posts:
    2
    not to be a downer, but the script scales all my objects to 0 along the x axis. It seems to ignore its cellsize parameter, or does not apply its calculations correctly

    Edit: To simply adjust width or height I created a script to attach to the gridlayoutgroup object.
    It gets the needed vales, calculates either width or height for a cell and reapplies the result

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. [ExecuteInEditMode]
    7. [RequireComponent(typeof(UnityEngine.UI.GridLayoutGroup))]
    8. public class AdjustGridLayoutCellSize : MonoBehaviour
    9. {
    10.     public enum ExpandSetting { X, Y,};
    11.  
    12.     public ExpandSetting expandingSetting;
    13.     GridLayoutGroup gridlayout;
    14.     int maxConstraintCount = 0;
    15.     RectTransform layoutRect;
    16.     private void Awake()
    17.     {
    18.         gridlayout = GetComponent<GridLayoutGroup>();
    19.     }
    20.  
    21.     // Start is called before the first frame update
    22.     void Start()
    23.     {
    24.         UpdateCellSize();
    25.     }
    26.  
    27.     // Update is called once per frame
    28.     void Update()
    29.     {
    30.        
    31.     }
    32.  
    33.     private void OnValidate()
    34.     {
    35.         UpdateCellSize();
    36.     }
    37.  
    38.     private void UpdateCellSize()
    39.     {
    40.         maxConstraintCount = gridlayout.constraintCount;
    41.         layoutRect = gridlayout.gameObject.GetComponent<RectTransform>();
    42.  
    43.         if (expandingSetting == ExpandSetting.X)
    44.         {
    45.             float width = layoutRect.rect.width;
    46.             float sizePerCell = width / maxConstraintCount;
    47.             gridlayout.cellSize = new Vector2(sizePerCell, gridlayout.cellSize.y);
    48.         }
    49.         else if (expandingSetting == ExpandSetting.Y)
    50.         {
    51.             float height = layoutRect.rect.height;
    52.             float sizePerCell = height / maxConstraintCount;
    53.             gridlayout.cellSize = new Vector2(gridlayout.cellSize.x, sizePerCell);
    54.         }
    55.     }
    56. }
    57.  
     
    Last edited: May 12, 2019
  12. pyjamads

    pyjamads

    Joined:
    Jun 12, 2013
    Posts:
    8
    cdr9042 likes this.
  13. vaices1974

    vaices1974

    Joined:
    Feb 4, 2019
    Posts:
    3
    I've updated the code to include spacing between cells.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. [ExecuteInEditMode]
    5. [RequireComponent(typeof(UnityEngine.UI.GridLayoutGroup))]
    6. public class AdjustGridLayoutCellSize : MonoBehaviour
    7. {
    8.     public enum ExpandSetting { X, Y };
    9.  
    10.     public ExpandSetting expandingSetting;
    11.     GridLayoutGroup _gridlayout;
    12.  
    13.     private GridLayoutGroup gridlayout
    14.     {
    15.         get
    16.         {
    17.             if(!_gridlayout)
    18.                 _gridlayout = GetComponent<GridLayoutGroup>();
    19.             return _gridlayout;
    20.         }      
    21.     }
    22.  
    23.     int maxConstraintCount = 0;
    24.     RectTransform layoutRect;
    25.  
    26.     // Start is called before the first frame update
    27.     void Start()
    28.     {      
    29.         UpdateCellSize();
    30.     }
    31.  
    32.    
    33.     private void OnValidate()
    34.     {
    35.         UpdateCellSize();
    36.     }
    37.  
    38.     private void UpdateCellSize()
    39.     {
    40.         maxConstraintCount = gridlayout.constraintCount;
    41.         layoutRect = gridlayout.gameObject.GetComponent<RectTransform>();
    42.  
    43.         if (expandingSetting == ExpandSetting.X)
    44.         {
    45.             float spaceForSpacing = (maxConstraintCount - 1) * gridlayout.spacing.x;
    46.             float width = layoutRect.rect.width - spaceForSpacing;
    47.          
    48.             float sizePerCell = width / maxConstraintCount ;
    49.             gridlayout.cellSize = new Vector2(sizePerCell, gridlayout.cellSize.y);
    50.         }
    51.         else if (expandingSetting == ExpandSetting.Y)
    52.         {
    53.             float spaceForSpacing = (maxConstraintCount - 1) * gridlayout.spacing.y;
    54.             float height = layoutRect.rect.height - spaceForSpacing;
    55.             float sizePerCell = height / maxConstraintCount;
    56.             gridlayout.cellSize = new Vector2(gridlayout.cellSize.x, sizePerCell);
    57.         }
    58.     }
    59. }
    60.  
     
    BigGameCompany and outofcoffee like this.
  14. tyapichu

    tyapichu

    Joined:
    Aug 11, 2013
    Posts:
    11
    i've added aspect ratio control to code, because when i added Aspect Ratio Control to an object inside Grid Layout Content Size Filter of that grid didn't work as it should.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. [ExecuteInEditMode]
    5. [RequireComponent(typeof(UnityEngine.UI.GridLayoutGroup))]
    6. public class AdjustGridLayoutCellSize : MonoBehaviour
    7. {
    8.     public enum ExpandSetting { X, Y };
    9.  
    10.     public ExpandSetting expandingSetting;
    11.     GridLayoutGroup _gridlayout;
    12.  
    13.     public bool aspectTurn;
    14.     public float aspectRatio;
    15.  
    16.     private GridLayoutGroup gridlayout
    17.     {
    18.         get
    19.         {
    20.             if (!_gridlayout)
    21.                 _gridlayout = GetComponent<GridLayoutGroup>();
    22.             return _gridlayout;
    23.         }
    24.     }
    25.  
    26.     int maxConstraintCount = 0;
    27.     RectTransform layoutRect;
    28.  
    29.     // Start is called before the first frame update
    30.     void Start()
    31.     {
    32.         UpdateCellSize();
    33.     }
    34.  
    35.  
    36.     private void OnValidate()
    37.     {
    38.         UpdateCellSize();
    39.     }
    40.  
    41.     private void UpdateCellSize()
    42.     {
    43.         maxConstraintCount = gridlayout.constraintCount;
    44.         layoutRect = gridlayout.gameObject.GetComponent<RectTransform>();
    45.  
    46.         if (expandingSetting == ExpandSetting.X)
    47.         {
    48.             float spaceForSpacing = (maxConstraintCount - 1) * gridlayout.spacing.x;
    49.             float width = layoutRect.rect.width - spaceForSpacing;
    50.             float sizePerCell = width / maxConstraintCount;
    51.  
    52.             float x = sizePerCell;
    53.             float y = gridlayout.cellSize.y;
    54.             if (aspectTurn)
    55.                 y = x * aspectRatio;
    56.  
    57.             //gridlayout.cellSize = new Vector2(sizePerCell, gridlayout.cellSize.y);
    58.             gridlayout.cellSize = new Vector2(x, y);
    59.         }
    60.         else if (expandingSetting == ExpandSetting.Y)
    61.         {
    62.             float spaceForSpacing = (maxConstraintCount - 1) * gridlayout.spacing.y;
    63.             float height = layoutRect.rect.height - spaceForSpacing;
    64.             float sizePerCell = height / maxConstraintCount;
    65.  
    66.             float x = gridlayout.cellSize.x;
    67.             float y = sizePerCell;
    68.             if (aspectTurn)
    69.                 x = y * aspectRatio;
    70.  
    71.             //gridlayout.cellSize = new Vector2(gridlayout.cellSize.x, sizePerCell);
    72.             gridlayout.cellSize = new Vector2(x, y);
    73.         }
    74.     }
    75. }
     
  15. Lumpazy

    Lumpazy

    Joined:
    Apr 24, 2018
    Posts:
    45
    i only looked at the code for a few minutes, but it seems like exchanging line 207 should do the trick :

    float realsize = ((width - padding.left - padding.right - (spacing[0] * (actualCellCountX - 1))) / actualCellCountX);
     
  16. arturmandas

    arturmandas

    Joined:
    Sep 29, 2012
    Posts:
    240
    You've save me some serious cursing while setting up this on my own! Thanks!
     
  17. DeloitteCam

    DeloitteCam

    Joined:
    Jan 23, 2018
    Posts:
    22
    There's no need to replace GridLayoutGroup for this, that's adding a heap more code to maintain. The solution by Mathyx92 is a better approach IMO.

    Here's an updated version that adds the following:

    • Works with all GridLayoutGroup's settings (padding, spacing, constraints)
    • Added optional ratio mode for cells (force square or 2:1 etc)
    • Updates at runtime when rect transform is resized
    • Updates in editor when values changed
    • General code cleanup

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3.  
    4. [ExecuteInEditMode]
    5. [RequireComponent(typeof(GridLayoutGroup))]
    6. public class AdjustGridLayoutCellSize : MonoBehaviour
    7. {
    8.     public enum Axis { X, Y };
    9.     public enum RatioMode { Free, Fixed };
    10.    
    11.     [SerializeField] Axis expand;
    12.     [SerializeField] RatioMode ratioMode;
    13.     [SerializeField] float cellRatio = 1;
    14.  
    15.     new RectTransform transform;
    16.     GridLayoutGroup grid;
    17.  
    18.     void Awake()
    19.     {
    20.         transform = (RectTransform)base.transform;
    21.         grid = GetComponent<GridLayoutGroup>();
    22.     }
    23.  
    24.     // Start is called before the first frame update
    25.     void Start()
    26.     {
    27.         UpdateCellSize();
    28.     }
    29.  
    30.     void OnRectTransformDimensionsChange()
    31.     {
    32.         UpdateCellSize();
    33.     }
    34.  
    35. #if UNITY_EDITOR
    36.     [ExecuteAlways]
    37.     void Update()
    38.     {
    39.         UpdateCellSize();
    40.     }
    41. #endif
    42.  
    43.     void OnValidate()
    44.     {
    45.         transform = (RectTransform)base.transform;
    46.         grid = GetComponent<GridLayoutGroup>();
    47.         UpdateCellSize();
    48.     }
    49.  
    50.     void UpdateCellSize()
    51.     {
    52.         var count = grid.constraintCount;
    53.         if (expand == Axis.X)
    54.         {
    55.             float spacing = (count - 1) * grid.spacing.x;
    56.             float contentSize = transform.rect.width - grid.padding.left - grid.padding.right - spacing;
    57.             float sizePerCell = contentSize / count;
    58.             grid.cellSize = new Vector2(sizePerCell, ratioMode == RatioMode.Free ? grid.cellSize.y : sizePerCell * cellRatio);
    59.            
    60.         }
    61.         else //if (expand == Axis.Y)
    62.         {
    63.             float spacing = (count - 1) * grid.spacing.y;
    64.             float contentSize = transform.rect.height - grid.padding.top - grid.padding.bottom -spacing;
    65.             float sizePerCell = contentSize / count;
    66.             grid.cellSize = new Vector2(ratioMode == RatioMode.Free ? grid.cellSize.x : sizePerCell * cellRatio, sizePerCell);
    67.         }
    68.     }
    69. }
    70.  
     
  18. LuyaGames

    LuyaGames

    Joined:
    Jan 22, 2019
    Posts:
    19
    Thank you!
    I'm testing this solution with Unity 2019.4.5. It works great in Editor but once built (tried for Windows Standalone x64 and Android), it does'nt. Do you have it working in a built game?
     
  19. LuyaGames

    LuyaGames

    Joined:
    Jan 22, 2019
    Posts:
    19
    My bad... I populate the GridLayoutGroup from script and the items were re-scaled by Unity. I had to force the scale from my script. The element are correctly adjusted.
     
  20. Hukha

    Hukha

    Joined:
    Aug 12, 2013
    Posts:
    61
    Thanks you so much! Works great!
     
  21. mfatihbarut

    mfatihbarut

    Joined:
    Apr 11, 2018
    Posts:
    1,060
    Nope that is not the solution. I don't like overriding Unity's main files.
    The solution is this simple
    Code (CSharp):
    1.  
    2.    Vector2 YeniSize = new Vector2(549, 768);
    3.         KartScreen.GetComponent<GridLayoutGroup>().cellSize = YeniSize;
    thanks to this guy
     
    dougfinn22 likes this.
  22. sumpfkraut

    sumpfkraut

    Joined:
    Jan 18, 2013
    Posts:
    242
    GetComponent<> in the Update() method is not the best idea...

    I just do it with a Horizontal Layoutgroup, and Vertical Layoutgroups as Child objects.
     
    trombonaut likes this.
  23. mfatihbarut

    mfatihbarut

    Joined:
    Apr 11, 2018
    Posts:
    1,060
    why don't you get it at start() so?
    that is still the answer.
     
  24. Gabrio

    Gabrio

    Joined:
    Jan 31, 2016
    Posts:
    17
    Maybe it's not part of this post, but I've added a switch to expand the cellSpace instead of the cell size.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. [ExecuteInEditMode]
    4. [RequireComponent(typeof(GridLayoutGroup))]
    5. public class AdjustGridLayoutCellSize : MonoBehaviour
    6. {
    7.     public enum Axis { X, Y };
    8.     public enum RatioMode { Free, Fixed };
    9.     public enum Expand { cell, space };
    10.  
    11.     [SerializeField] Axis expand;
    12.     [SerializeField] RatioMode ratioMode;
    13.     [SerializeField] float cellRatio = 1;
    14.     [SerializeField] Expand type;
    15.  
    16.     new RectTransform transform;
    17.     GridLayoutGroup grid;
    18.     void Awake()
    19.     {
    20.         transform = (RectTransform)base.transform;
    21.         grid = GetComponent<GridLayoutGroup>();
    22.     }
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.         if (type == Expand.cell)
    27.             UpdateCellSize();
    28.         else if (type == Expand.space)
    29.             UpdateCellSpace();
    30.     }
    31.     void OnRectTransformDimensionsChange()
    32.     {
    33.         if (type == Expand.cell)
    34.             UpdateCellSize();
    35.         else if (type == Expand.space)
    36.             UpdateCellSpace();
    37.     }
    38. #if UNITY_EDITOR
    39.     [ExecuteAlways]
    40.     void Update()
    41.     {
    42.         if (type == Expand.cell)
    43.             UpdateCellSize();
    44.         else if (type == Expand.space)
    45.             UpdateCellSpace();
    46.     }
    47. #endif
    48.     void OnValidate()
    49.     {
    50.         transform = (RectTransform)base.transform;
    51.         grid = GetComponent<GridLayoutGroup>();
    52.         if (type == Expand.cell)
    53.             UpdateCellSize();
    54.         else if (type == Expand.space)
    55.             UpdateCellSpace();
    56.     }
    57.     void UpdateCellSize()
    58.     {
    59.         var count = grid.constraintCount;
    60.         if (expand == Axis.X)
    61.         {
    62.             float spacing = (count - 1) * grid.spacing.x;
    63.             float contentSize = transform.rect.width - grid.padding.left - grid.padding.right - spacing;
    64.             float sizePerCell = contentSize / count;
    65.             grid.cellSize = new Vector2(sizePerCell, ratioMode == RatioMode.Free ? grid.cellSize.y : sizePerCell * cellRatio);
    66.          
    67.         }
    68.         else //if (expand == Axis.Y)
    69.         {
    70.             float spacing = (count - 1) * grid.spacing.y;
    71.             float contentSize = transform.rect.height - grid.padding.top - grid.padding.bottom -spacing;
    72.             float sizePerCell = contentSize / count;
    73.             grid.cellSize = new Vector2(ratioMode == RatioMode.Free ? grid.cellSize.x : sizePerCell * cellRatio, sizePerCell);
    74.         }
    75.     }
    76.  
    77.     void UpdateCellSpace()
    78.     {
    79.         var count = grid.constraintCount;
    80.         if (expand == Axis.X)
    81.         {
    82.  
    83.             float contentSize = count * grid.cellSize.x;
    84.             float spacing = transform.rect.width - grid.padding.left - grid.padding.right - contentSize;
    85.             float spacePerCell = Mathf.Clamp(spacing / (count + 1), 0, grid.cellSize.x / 2.0f);
    86.             grid.spacing = new Vector2(spacePerCell, ratioMode == RatioMode.Free ? grid.spacing.y : spacePerCell * cellRatio);
    87.  
    88.         }
    89.         else //if (expand == Axis.Y)
    90.         {
    91.             float contentSize = count * grid.cellSize.y;
    92.             float spacing = transform.rect.height - grid.padding.top - grid.padding.bottom - contentSize;
    93.             float spacePerCell = Mathf.Clamp(spacing / (count + 1), 0, grid.cellSize.y / 2.0f);
    94.             grid.spacing = new Vector2(ratioMode == RatioMode.Free ? grid.spacing.x : spacePerCell * cellRatio, spacePerCell);
    95.         }
    96.     }
    97. }
     
  25. 1000Nettles

    1000Nettles

    Joined:
    Aug 25, 2013
    Posts:
    3
    This was the script that saved me from my UI nightmares, thank you 100 times over. Really elegant solution too to avoid overwriting the core Grid Layout Group component.
     
    Rekastt likes this.
  26. carored

    carored

    Joined:
    Mar 21, 2018
    Posts:
    11
    this line gives me an error, 52: "var count = grid.constraintCount;"
    NullReferenceException: Object reference not set to an instance of an object
     
    Leute likes this.
  27. restush96

    restush96

    Joined:
    May 28, 2019
    Posts:
    144
    I have make grid with flexible width and height, support any resolution and keep ratio without codes by using unity built-in vertical and horizontal layout.

    if you want like this:

    VT[
    A[XX1 XX2]
    B[XX1 XX2]
    C[XX1 XX2]
    ]


    Here is the steps: (make sure you have knowledge in control child size, child force expand, and layout element)

    1. Make horizontal of children XX1, adjust the horizontal value
    2. Then make parent of XX1 that become A, then add horizontal in A
    3. In child of A, duplicate XX1 to become XX2, then adjust horizontal value of A
    4. Make parent of A that become VT, then add vertical to VT, adjust vertical layout
    5. Finish, you just need duplicate A inside VT to become B and C

    Your gameobjects should have looks like this:

    upload_2023-8-19_22-44-1.png

    My contain of XX1 is icon, level, 99.999.
    upload_2023-8-19_22-46-55.png
     
  28. filippofrattapasini

    filippofrattapasini

    Joined:
    Oct 19, 2022
    Posts:
    1
    Love you!