UI update 02
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[AddComponentMenu("Layout/Flow Layout Group")]
|
||||
public class FlowLayoutGroup : LayoutGroup
|
||||
{
|
||||
[SerializeField] private float spacingX = 10f;
|
||||
[SerializeField] private float spacingY = 10f;
|
||||
[SerializeField] private bool expandChildHeight = false;
|
||||
[SerializeField] private float forcedChildHeight = 120f;
|
||||
|
||||
private readonly List<RowInfo> rows = new List<RowInfo>();
|
||||
private float calculatedPreferredHeight;
|
||||
|
||||
private struct RowInfo
|
||||
{
|
||||
public int startIndex;
|
||||
public int endIndex;
|
||||
public float width;
|
||||
public float height;
|
||||
}
|
||||
|
||||
public float SpacingX
|
||||
{
|
||||
get => spacingX;
|
||||
set => SetProperty(ref spacingX, value);
|
||||
}
|
||||
|
||||
public float SpacingY
|
||||
{
|
||||
get => spacingY;
|
||||
set => SetProperty(ref spacingY, value);
|
||||
}
|
||||
|
||||
public bool ExpandChildHeight
|
||||
{
|
||||
get => expandChildHeight;
|
||||
set => SetProperty(ref expandChildHeight, value);
|
||||
}
|
||||
|
||||
public float ForcedChildHeight
|
||||
{
|
||||
get => forcedChildHeight;
|
||||
set => SetProperty(ref forcedChildHeight, value);
|
||||
}
|
||||
|
||||
public override void CalculateLayoutInputHorizontal()
|
||||
{
|
||||
base.CalculateLayoutInputHorizontal();
|
||||
CalculateRows();
|
||||
float minWidth = padding.horizontal;
|
||||
float preferredWidth = rectTransform.rect.width > 0f ? rectTransform.rect.width : minWidth;
|
||||
SetLayoutInputForAxis(minWidth, preferredWidth, -1f, 0);
|
||||
}
|
||||
|
||||
public override void CalculateLayoutInputVertical()
|
||||
{
|
||||
CalculateRows();
|
||||
SetLayoutInputForAxis(calculatedPreferredHeight, calculatedPreferredHeight, -1f, 1);
|
||||
}
|
||||
|
||||
public override void SetLayoutHorizontal()
|
||||
{
|
||||
CalculateRows();
|
||||
SetChildrenAlongAxis();
|
||||
}
|
||||
|
||||
public override void SetLayoutVertical()
|
||||
{
|
||||
CalculateRows();
|
||||
SetChildrenAlongAxis();
|
||||
}
|
||||
|
||||
private void CalculateRows()
|
||||
{
|
||||
rows.Clear();
|
||||
|
||||
float availableWidth = GetAvailableWidth();
|
||||
|
||||
float currentRowWidth = 0f;
|
||||
float currentRowHeight = 0f;
|
||||
int currentRowStart = 0;
|
||||
bool hasRow = false;
|
||||
|
||||
for (int i = 0; i < rectChildren.Count; i++)
|
||||
{
|
||||
RectTransform child = rectChildren[i];
|
||||
if (child == null) continue;
|
||||
|
||||
float childWidth = Mathf.Max(LayoutUtility.GetPreferredSize(child, 0), LayoutUtility.GetMinSize(child, 0), child.rect.width);
|
||||
float childHeight = expandChildHeight
|
||||
? forcedChildHeight
|
||||
: Mathf.Max(LayoutUtility.GetPreferredSize(child, 1), LayoutUtility.GetMinSize(child, 1), child.rect.height);
|
||||
|
||||
float requiredWidth = hasRow ? currentRowWidth + spacingX + childWidth : childWidth;
|
||||
bool shouldWrap = hasRow && requiredWidth > availableWidth;
|
||||
|
||||
if (shouldWrap)
|
||||
{
|
||||
rows.Add(new RowInfo
|
||||
{
|
||||
startIndex = currentRowStart,
|
||||
endIndex = i - 1,
|
||||
width = currentRowWidth,
|
||||
height = currentRowHeight
|
||||
});
|
||||
|
||||
currentRowStart = i;
|
||||
currentRowWidth = childWidth;
|
||||
currentRowHeight = childHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentRowWidth = hasRow ? requiredWidth : childWidth;
|
||||
currentRowHeight = Mathf.Max(currentRowHeight, childHeight);
|
||||
hasRow = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasRow)
|
||||
{
|
||||
rows.Add(new RowInfo
|
||||
{
|
||||
startIndex = currentRowStart,
|
||||
endIndex = rectChildren.Count - 1,
|
||||
width = currentRowWidth,
|
||||
height = currentRowHeight
|
||||
});
|
||||
}
|
||||
|
||||
calculatedPreferredHeight = padding.vertical;
|
||||
for (int i = 0; i < rows.Count; i++)
|
||||
{
|
||||
calculatedPreferredHeight += rows[i].height;
|
||||
if (i < rows.Count - 1)
|
||||
{
|
||||
calculatedPreferredHeight += spacingY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetChildrenAlongAxis()
|
||||
{
|
||||
float availableWidth = GetAvailableWidth();
|
||||
float y = padding.top;
|
||||
|
||||
for (int rowIndex = 0; rowIndex < rows.Count; rowIndex++)
|
||||
{
|
||||
RowInfo row = rows[rowIndex];
|
||||
float startX = GetRowStartX(availableWidth, row.width);
|
||||
float x = startX;
|
||||
|
||||
for (int i = row.startIndex; i <= row.endIndex; i++)
|
||||
{
|
||||
RectTransform child = rectChildren[i];
|
||||
if (child == null) continue;
|
||||
|
||||
float childWidth = Mathf.Max(LayoutUtility.GetPreferredSize(child, 0), LayoutUtility.GetMinSize(child, 0), child.rect.width);
|
||||
float childHeight = expandChildHeight
|
||||
? forcedChildHeight
|
||||
: Mathf.Max(LayoutUtility.GetPreferredSize(child, 1), LayoutUtility.GetMinSize(child, 1), child.rect.height);
|
||||
|
||||
float offsetY = GetChildVerticalOffset(row.height, childHeight);
|
||||
SetChildAlongAxis(child, 0, x, childWidth);
|
||||
SetChildAlongAxis(child, 1, y + offsetY, childHeight);
|
||||
x += childWidth + spacingX;
|
||||
}
|
||||
|
||||
y += row.height + spacingY;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetRowStartX(float availableWidth, float rowWidth)
|
||||
{
|
||||
TextAnchor anchor = childAlignment;
|
||||
switch (anchor)
|
||||
{
|
||||
case TextAnchor.UpperCenter:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.LowerCenter:
|
||||
return padding.left + Mathf.Max(0f, (availableWidth - rowWidth) * 0.5f);
|
||||
|
||||
case TextAnchor.UpperRight:
|
||||
case TextAnchor.MiddleRight:
|
||||
case TextAnchor.LowerRight:
|
||||
return padding.left + Mathf.Max(0f, availableWidth - rowWidth);
|
||||
|
||||
default:
|
||||
return padding.left;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetChildVerticalOffset(float rowHeight, float childHeight)
|
||||
{
|
||||
TextAnchor anchor = childAlignment;
|
||||
switch (anchor)
|
||||
{
|
||||
case TextAnchor.MiddleLeft:
|
||||
case TextAnchor.MiddleCenter:
|
||||
case TextAnchor.MiddleRight:
|
||||
return Mathf.Max(0f, (rowHeight - childHeight) * 0.5f);
|
||||
|
||||
case TextAnchor.LowerLeft:
|
||||
case TextAnchor.LowerCenter:
|
||||
case TextAnchor.LowerRight:
|
||||
return Mathf.Max(0f, rowHeight - childHeight);
|
||||
|
||||
default:
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetAvailableWidth()
|
||||
{
|
||||
float availableWidth = rectTransform.rect.width - padding.horizontal;
|
||||
if (availableWidth > 0f)
|
||||
{
|
||||
return availableWidth;
|
||||
}
|
||||
|
||||
RectTransform parentRect = rectTransform.parent as RectTransform;
|
||||
if (parentRect != null)
|
||||
{
|
||||
availableWidth = parentRect.rect.width - padding.horizontal;
|
||||
if (availableWidth > 0f)
|
||||
{
|
||||
return availableWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return float.PositiveInfinity;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user