Updated Table Layout Group component for release and added docs

--HG--
branch : develop_5.3
release
Simon Jackson 2016-12-30 17:28:34 +00:00
parent 473c0f3757
commit 909589e544
2 changed files with 302 additions and 289 deletions

View File

@ -1,290 +1,291 @@
/// Credit RahulOfTheRamanEffect /// Credit RahulOfTheRamanEffect
/// Sourced from - https://forum.unity3d.com/members/rahuloftheramaneffect.773241/ /// Sourced from - https://forum.unity3d.com/members/rahuloftheramaneffect.773241/
namespace UnityEngine.UI.Extensions namespace UnityEngine.UI.Extensions
{ {
/// <summary> /// <summary>
/// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights /// Arranges child objects into a non-uniform grid, with fixed column widths and flexible row heights
/// </summary> /// </summary>
public class TableLayoutGroup : LayoutGroup [AddComponentMenu("Layout/Extensions/Table Layout Group")]
{ public class TableLayoutGroup : LayoutGroup
public enum Corner {
{ public enum Corner
UpperLeft = 0, {
UpperRight = 1, UpperLeft = 0,
LowerLeft = 2, UpperRight = 1,
LowerRight = 3 LowerLeft = 2,
} LowerRight = 3
}
[SerializeField]
protected Corner startCorner = Corner.UpperLeft; [SerializeField]
/// <summary> protected Corner startCorner = Corner.UpperLeft;
/// The corner starting from which the cells should be arranged /// <summary>
/// </summary> /// The corner starting from which the cells should be arranged
public Corner StartCorner /// </summary>
{ public Corner StartCorner
get { return startCorner; } {
set get { return startCorner; }
{ set
SetProperty(ref startCorner, value); {
} SetProperty(ref startCorner, value);
} }
}
[SerializeField]
protected float[] columnWidths = new float[1] { 96f }; [SerializeField]
/// <summary> protected float[] columnWidths = new float[1] { 96f };
/// The widths of all the columns in the table /// <summary>
/// </summary> /// The widths of all the columns in the table
public float[] ColumnWidths /// </summary>
{ public float[] ColumnWidths
get { return columnWidths; } {
set get { return columnWidths; }
{ set
SetProperty(ref columnWidths, value); {
} SetProperty(ref columnWidths, value);
} }
}
[SerializeField]
protected float minimumRowHeight = 32f; [SerializeField]
/// <summary> protected float minimumRowHeight = 32f;
/// The minimum height for any row in the table /// <summary>
/// </summary> /// The minimum height for any row in the table
public float MinimumRowHeight /// </summary>
{ public float MinimumRowHeight
get { return minimumRowHeight; } {
set get { return minimumRowHeight; }
{ set
SetProperty(ref minimumRowHeight, value); {
} SetProperty(ref minimumRowHeight, value);
} }
}
[SerializeField]
protected bool flexibleRowHeight = true; [SerializeField]
/// <summary> protected bool flexibleRowHeight = true;
/// Expand rows to fit the cell with the highest preferred height? /// <summary>
/// </summary> /// Expand rows to fit the cell with the highest preferred height?
public bool FlexibleRowHeight /// </summary>
{ public bool FlexibleRowHeight
get { return flexibleRowHeight; } {
set get { return flexibleRowHeight; }
{ set
SetProperty(ref flexibleRowHeight, value); {
} SetProperty(ref flexibleRowHeight, value);
} }
}
[SerializeField]
protected float columnSpacing = 0f; [SerializeField]
/// <summary> protected float columnSpacing = 0f;
/// The horizontal spacing between each cell in the table /// <summary>
/// </summary> /// The horizontal spacing between each cell in the table
public float ColumnSpacing /// </summary>
{ public float ColumnSpacing
get { return columnSpacing; } {
set get { return columnSpacing; }
{ set
SetProperty(ref columnSpacing, value); {
} SetProperty(ref columnSpacing, value);
} }
}
[SerializeField]
protected float rowSpacing = 0; [SerializeField]
/// <summary> protected float rowSpacing = 0;
/// The vertical spacing between each row in the table /// <summary>
/// </summary> /// The vertical spacing between each row in the table
public float RowSpacing /// </summary>
{ public float RowSpacing
get { return rowSpacing; } {
set get { return rowSpacing; }
{ set
SetProperty(ref rowSpacing, value); {
} SetProperty(ref rowSpacing, value);
} }
}
// Temporarily stores data generated during the execution CalculateLayoutInputVertical for use in SetLayoutVertical
private float[] preferredRowHeights; // Temporarily stores data generated during the execution CalculateLayoutInputVertical for use in SetLayoutVertical
private float[] preferredRowHeights;
public override void CalculateLayoutInputHorizontal()
{ public override void CalculateLayoutInputHorizontal()
base.CalculateLayoutInputHorizontal(); {
base.CalculateLayoutInputHorizontal();
float horizontalSize = padding.horizontal;
float horizontalSize = padding.horizontal;
// We calculate the actual cell count for cases where the number of children is lesser than the number of columns
int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); // We calculate the actual cell count for cases where the number of children is lesser than the number of columns
int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length);
for (int i = 0; i < actualCellCount; i++)
{ for (int i = 0; i < actualCellCount; i++)
horizontalSize += columnWidths[i]; {
horizontalSize += columnSpacing; horizontalSize += columnWidths[i];
} horizontalSize += columnSpacing;
}
horizontalSize -= columnSpacing;
horizontalSize -= columnSpacing;
SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0);
} SetLayoutInputForAxis(horizontalSize, horizontalSize, 0, 0);
}
public override void CalculateLayoutInputVertical()
{ public override void CalculateLayoutInputVertical()
int columnCount = columnWidths.Length; {
int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount); int columnCount = columnWidths.Length;
int rowCount = Mathf.CeilToInt(rectChildren.Count / (float)columnCount);
preferredRowHeights = new float[rowCount];
preferredRowHeights = new float[rowCount];
float totalMinHeight = padding.vertical;
float totalPreferredHeight = padding.vertical; float totalMinHeight = padding.vertical;
float totalPreferredHeight = padding.vertical;
if (rowCount > 1)
{ if (rowCount > 1)
float heightFromSpacing = ((rowCount - 1) * rowSpacing); {
totalMinHeight += heightFromSpacing; float heightFromSpacing = ((rowCount - 1) * rowSpacing);
totalPreferredHeight += heightFromSpacing; totalMinHeight += heightFromSpacing;
} totalPreferredHeight += heightFromSpacing;
}
if (flexibleRowHeight)
{ if (flexibleRowHeight)
// If flexibleRowHeight is enabled, find the max value for minimum and preferred heights in each row {
// If flexibleRowHeight is enabled, find the max value for minimum and preferred heights in each row
float maxMinimumHeightInRow = 0;
float maxPreferredHeightInRow = 0; float maxMinimumHeightInRow = 0;
float maxPreferredHeightInRow = 0;
for (int i = 0; i < rectChildren.Count; i++)
{ for (int i = 0; i < rectChildren.Count; i++)
int currentRowIndex = i / columnCount; {
int currentColumnIndex = i % columnCount; int currentRowIndex = i / columnCount;
int currentColumnIndex = i % columnCount;
// If it's the first cell in the row, reset heights for the row
if (currentColumnIndex == 0) // If it's the first cell in the row, reset heights for the row
{ if (currentColumnIndex == 0)
maxMinimumHeightInRow = minimumRowHeight; {
maxPreferredHeightInRow = minimumRowHeight; maxMinimumHeightInRow = minimumRowHeight;
} maxPreferredHeightInRow = minimumRowHeight;
}
maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[i]), maxPreferredHeightInRow);
maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[i]), maxMinimumHeightInRow); maxPreferredHeightInRow = Mathf.Max(LayoutUtility.GetPreferredHeight(rectChildren[i]), maxPreferredHeightInRow);
maxMinimumHeightInRow = Mathf.Max(LayoutUtility.GetMinHeight(rectChildren[i]), maxMinimumHeightInRow);
// If it's the last cell in the row, or if it's the last cell and the row is incomplete, set calculated heights
if (currentColumnIndex == columnCount - 1 || (i == rectChildren.Count - 1 && currentRowIndex == rowCount - 1)) // If it's the last cell in the row, or if it's the last cell and the row is incomplete, set calculated heights
{ if (currentColumnIndex == columnCount - 1 || (i == rectChildren.Count - 1 && currentRowIndex == rowCount - 1))
totalMinHeight += maxMinimumHeightInRow; {
totalPreferredHeight += maxPreferredHeightInRow; totalMinHeight += maxMinimumHeightInRow;
totalPreferredHeight += maxPreferredHeightInRow;
// Add calculated row height to a commonly accessible array for reuse in SetLayoutVertical()
preferredRowHeights[currentRowIndex] = maxPreferredHeightInRow; // Add calculated row height to a commonly accessible array for reuse in SetLayoutVertical()
} preferredRowHeights[currentRowIndex] = maxPreferredHeightInRow;
} }
} }
else }
{ else
// If flexibleRowHeight is disabled, then use the minimumRowHeight to calculate vertical layout information {
for (int i = 0; i < rowCount; i++) // If flexibleRowHeight is disabled, then use the minimumRowHeight to calculate vertical layout information
preferredRowHeights[i] = minimumRowHeight; for (int i = 0; i < rowCount; i++)
preferredRowHeights[i] = minimumRowHeight;
totalMinHeight += rowCount * minimumRowHeight;
totalPreferredHeight = totalMinHeight; totalMinHeight += rowCount * minimumRowHeight;
} totalPreferredHeight = totalMinHeight;
}
totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight);
SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1); totalPreferredHeight = Mathf.Max(totalMinHeight, totalPreferredHeight);
} SetLayoutInputForAxis(totalMinHeight, totalPreferredHeight, 1, 1);
}
public override void SetLayoutHorizontal()
{ public override void SetLayoutHorizontal()
// If no column width is defined, then assign a reasonable default {
if (columnWidths.Length == 0) // If no column width is defined, then assign a reasonable default
columnWidths = new float[1] { 0f }; if (columnWidths.Length == 0)
columnWidths = new float[1] { 0f };
int columnCount = columnWidths.Length;
int cornerX = (int)startCorner % 2; int columnCount = columnWidths.Length;
int cornerX = (int)startCorner % 2;
float startOffset = 0;
float requiredSizeWithoutPadding = 0; float startOffset = 0;
float requiredSizeWithoutPadding = 0;
// We calculate the actual cell count for cases where the number of children is lesser than the number of columns
int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length); // We calculate the actual cell count for cases where the number of children is lesser than the number of columns
int actualCellCount = Mathf.Min(rectChildren.Count, columnWidths.Length);
for (int i = 0; i < actualCellCount; i++)
{ for (int i = 0; i < actualCellCount; i++)
requiredSizeWithoutPadding += columnWidths[i]; {
requiredSizeWithoutPadding += columnSpacing; requiredSizeWithoutPadding += columnWidths[i];
} requiredSizeWithoutPadding += columnSpacing;
}
requiredSizeWithoutPadding -= columnSpacing;
requiredSizeWithoutPadding -= columnSpacing;
startOffset = GetStartOffset(0, requiredSizeWithoutPadding);
startOffset = GetStartOffset(0, requiredSizeWithoutPadding);
if (cornerX == 1)
startOffset += requiredSizeWithoutPadding; if (cornerX == 1)
startOffset += requiredSizeWithoutPadding;
float positionX = startOffset;
float positionX = startOffset;
for (int i = 0; i < rectChildren.Count; i++)
{ for (int i = 0; i < rectChildren.Count; i++)
int currentColumnIndex = i % columnCount; {
int currentColumnIndex = i % columnCount;
// If it's the first cell in the row, reset positionX
if (currentColumnIndex == 0) // If it's the first cell in the row, reset positionX
positionX = startOffset; if (currentColumnIndex == 0)
positionX = startOffset;
if (cornerX == 1)
positionX -= columnWidths[currentColumnIndex]; if (cornerX == 1)
positionX -= columnWidths[currentColumnIndex];
SetChildAlongAxis(rectChildren[i], 0, positionX, columnWidths[currentColumnIndex]);
SetChildAlongAxis(rectChildren[i], 0, positionX, columnWidths[currentColumnIndex]);
if (cornerX == 1)
positionX -= columnSpacing; if (cornerX == 1)
else positionX -= columnSpacing;
positionX += columnWidths[currentColumnIndex] + columnSpacing; else
} positionX += columnWidths[currentColumnIndex] + columnSpacing;
} }
}
public override void SetLayoutVertical()
{ public override void SetLayoutVertical()
int columnCount = columnWidths.Length; {
int rowCount = preferredRowHeights.Length; int columnCount = columnWidths.Length;
int rowCount = preferredRowHeights.Length;
int cornerY = (int)startCorner / 2;
int cornerY = (int)startCorner / 2;
float startOffset = 0;
float requiredSizeWithoutPadding = 0; float startOffset = 0;
float requiredSizeWithoutPadding = 0;
for (int i = 0; i < rowCount; i++)
{ for (int i = 0; i < rowCount; i++)
requiredSizeWithoutPadding += preferredRowHeights[i]; {
requiredSizeWithoutPadding += rowSpacing; requiredSizeWithoutPadding += preferredRowHeights[i];
} requiredSizeWithoutPadding += rowSpacing;
}
requiredSizeWithoutPadding -= rowSpacing;
requiredSizeWithoutPadding -= rowSpacing;
startOffset = GetStartOffset(1, requiredSizeWithoutPadding);
startOffset = GetStartOffset(1, requiredSizeWithoutPadding);
if (cornerY == 1)
startOffset += requiredSizeWithoutPadding; if (cornerY == 1)
startOffset += requiredSizeWithoutPadding;
float positionY = startOffset;
float positionY = startOffset;
for (int i = 0; i < rectChildren.Count; i++)
{ for (int i = 0; i < rectChildren.Count; i++)
int currentRowIndex = i / columnCount; {
int currentColumnIndex = i % columnCount; int currentRowIndex = i / columnCount;
int currentColumnIndex = i % columnCount;
// If it's the first cell in the row and start corner is one of the bottom corners, then modify positionY appropriately
if (currentColumnIndex == 0 && cornerY == 1) // If it's the first cell in the row and start corner is one of the bottom corners, then modify positionY appropriately
positionY -= preferredRowHeights[currentRowIndex]; if (currentColumnIndex == 0 && cornerY == 1)
positionY -= preferredRowHeights[currentRowIndex];
SetChildAlongAxis(rectChildren[i], 1, positionY, preferredRowHeights[currentRowIndex]);
SetChildAlongAxis(rectChildren[i], 1, positionY, preferredRowHeights[currentRowIndex]);
// If it's the first last cell in the row, then modify positionY appropriately
if (currentColumnIndex == columnCount - 1) // If it's the first last cell in the row, then modify positionY appropriately
{ if (currentColumnIndex == columnCount - 1)
if (cornerY == 1) {
positionY -= rowSpacing; if (cornerY == 1)
else positionY -= rowSpacing;
positionY += preferredRowHeights[currentRowIndex] + rowSpacing; else
} positionY += preferredRowHeights[currentRowIndex] + rowSpacing;
} }
}
// Set preferredRowHeights to null to free memory
preferredRowHeights = null; // Set preferredRowHeights to null to free memory
} preferredRowHeights = null;
} }
}
} }

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6cee1f3bb43ca9c4c9e00b54a998d9ce
timeCreated: 1483117134
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: