Unity
Grid Layout Center 정렬하기
푸쿠이
2022. 4. 21. 14:28
원래는 Grid Layout Center를 사용하면 차곡차곡 정렬이 되는데,
Center를 중심으로 정렬하려면 요것을 쓰면 된다.
오브젝트에 Grid Layout Group 추가하듯이, Grid Layout Group Center 추가해서 사용하면 된다.
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 참고 문서.
/// https://forum.unity.com/threads/arrange-ui-elements-with-auto-centering-grid-layout-group.669127/
/// </summary>
[AddComponentMenu("Grid Layout Group Center")]
public class GridLayoutGroupCenter : UnityEngine.UI.GridLayoutGroup
{
public override void SetLayoutHorizontal()
{
SetCellsAlongAxis(0);
}
public override void SetLayoutVertical()
{
SetCellsAlongAxis(1);
}
private void SetCellsAlongAxis(int axis)
{
// Normally a Layout Controller should only set horizontal values when invoked for the horizontal axis
// and only vertical values when invoked for the vertical axis.
// However, in this case we set both the horizontal and vertical position when invoked for the vertical axis.
// Since we only set the horizontal position and not the size, it shouldn't affect children's layout,
// and thus shouldn't break the rule that all horizontal layout must be calculated before all vertical layout.
var rectChildrenCount = rectChildren.Count;
if (axis == 0)
{
// Only set the sizes when invoked for horizontal axis, not the positions.
for (int i = 0; i < rectChildrenCount; i++)
{
RectTransform rect = rectChildren[i];
m_Tracker.Add(this, rect,
DrivenTransformProperties.Anchors |
DrivenTransformProperties.AnchoredPosition |
DrivenTransformProperties.SizeDelta);
rect.anchorMin = Vector2.up;
rect.anchorMax = Vector2.up;
rect.sizeDelta = cellSize;
}
return;
}
float width = rectTransform.rect.size.x;
float height = rectTransform.rect.size.y;
int cellCountX = 1;
int cellCountY = 1;
if (m_Constraint == Constraint.FixedColumnCount)
{
cellCountX = m_ConstraintCount;
if (rectChildrenCount > cellCountX)
cellCountY = rectChildrenCount / cellCountX + (rectChildrenCount % cellCountX > 0 ? 1 : 0);
}
else if (m_Constraint == Constraint.FixedRowCount)
{
cellCountY = m_ConstraintCount;
if (rectChildrenCount > cellCountY)
cellCountX = rectChildrenCount / cellCountY + (rectChildrenCount % cellCountY > 0 ? 1 : 0);
}
else
{
if (cellSize.x + spacing.x <= 0)
cellCountX = int.MaxValue;
else
cellCountX = Mathf.Max(1, Mathf.FloorToInt((width - padding.horizontal + spacing.x + 0.001f) / (cellSize.x + spacing.x)));
if (cellSize.y + spacing.y <= 0)
cellCountY = int.MaxValue;
else
cellCountY = Mathf.Max(1, Mathf.FloorToInt((height - padding.vertical + spacing.y + 0.001f) / (cellSize.y + spacing.y)));
}
int cornerX = (int)startCorner % 2;
int cornerY = (int)startCorner / 2;
int cellsPerMainAxis, actualCellCountX, actualCellCountY;
if (startAxis == Axis.Horizontal)
{
cellsPerMainAxis = cellCountX;
actualCellCountX = Mathf.Clamp(cellCountX, 1, rectChildrenCount);
actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildrenCount / (float)cellsPerMainAxis));
}
else
{
cellsPerMainAxis = cellCountY;
actualCellCountY = Mathf.Clamp(cellCountY, 1, rectChildrenCount);
actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildrenCount / (float)cellsPerMainAxis));
}
int lastCellsCount = rectChildrenCount % cellsPerMainAxis;
Vector2 requiredSpace = new Vector2(
actualCellCountX * cellSize.x + (actualCellCountX - 1) * spacing.x,
actualCellCountY * cellSize.y + (actualCellCountY - 1) * spacing.y
);
Vector2 startOffset = new Vector2(
GetStartOffset(0, requiredSpace.x),
GetStartOffset(1, requiredSpace.y)
);
int actualLastCellsCount = lastCellsCount == 0 ? cellsPerMainAxis : lastCellsCount;
int cellsX = startAxis == Axis.Horizontal ? actualLastCellsCount : actualCellCountX;
int cellsY = startAxis == Axis.Vertical ? actualLastCellsCount : actualCellCountY;
Vector2 lastCellsRequiredSpace = new Vector2(
cellsX * cellSize.x + (cellsX - 1) * spacing.x,
cellsY * cellSize.y + (cellsY - 1) * spacing.y
);
Vector2 lastCellsStartOffset = new Vector2(
GetStartOffset(0, lastCellsRequiredSpace.x),
GetStartOffset(1, lastCellsRequiredSpace.y)
);
for (int i = 0; i < rectChildrenCount; i++)
{
int positionX;
int positionY;
Vector2 cellStartOffset = (i + 1 > rectChildrenCount - actualLastCellsCount) ? lastCellsStartOffset : startOffset;
if (startAxis == Axis.Horizontal)
{
positionX = i % cellsPerMainAxis;
positionY = i / cellsPerMainAxis;
}
else
{
positionX = i / cellsPerMainAxis;
positionY = i % cellsPerMainAxis;
}
if (cornerX == 1)
positionX = actualCellCountX - 1 - positionX;
if (cornerY == 1)
positionY = actualCellCountY - 1 - positionY;
SetChildAlongAxis(rectChildren[i], 0, cellStartOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
SetChildAlongAxis(rectChildren[i], 1, cellStartOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
}
}
}
이 코드를 쓰다보니,
ㅇㅇㅇ
-ㅇ-ㅇ-가 아니라
-ㅇ-ㅇ-
ㅇㅇㅇ 모양도 필요해서 코드를 수정하려헀으나!! 생각보다 쉽게 안 고쳐질 거 같아서,
임시방편으로 Start Corner를 Upper Left -> Lower Left 로 바꾸었다.
1 2
345 가 아니라서 마음에 안들긴하지만, 일단은 써야겠다.