【U3D】对GridLayoutGourp的重写实现适配
原因是在做一个项目的时候,策划要求的展示效果与grid的实现效果不一致
Grid对最后不能铺满的一行不能根据设置的Alignment进行对齐,又不懒得自己去算。故此对GridLayoutGourp进行重写,实现最后一行按照Alignment进行对齐
2023-05-13: 添加紧缩功能
2023-05-14: 更新代码结构 适应不同轴和childAlignment的紧缩
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AdapGridLayoutGroup : GridLayoutGroup
{
public bool austerity;
public override void CalculateLayoutInputHorizontal()
{
base.CalculateLayoutInputHorizontal();
}
public override void CalculateLayoutInputVertical()
{
base.CalculateLayoutInputVertical();
}
public override void SetLayoutHorizontal()
{
SetCellsAlongAxis(0);
}
public override void SetLayoutVertical()
{
SetCellsAlongAxis(1);
}
float GetRealSizeAxis(int axis, float count)
{
float v = Mathf.Max(cellSize[axis], rectTransform.rect.size[axis]- (axis == 0 ? padding.left : padding.top)) / count;
v -= (cellSize[axis] - v) / Mathf.Max(count - 1, 1) + spacing[axis];
return v;
}
private void SetCellsAlongAxis(int axis)
{
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));
}
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)
);
var realSize = cellSize;
if (austerity)
{
int axis1 = m_Constraint == Constraint.FixedRowCount ? 0 : 1;
float v1 = GetRealSizeAxis(axis1, (float)(axis1 == 0 ? cellCountX : cellCountY));
if (v1 < cellSize[axis1])
{
realSize[axis1] = v1;
startOffset[axis1] = axis1 == 0 ? padding.left : padding.top;
}
}
int endRowCount = rectChildrenCount % cellsPerMainAxis;
int endRowStart = rectChildrenCount - endRowCount;
for (int i = 0; i < rectChildrenCount; i++)
{
// 在最后一行开始的时候更新开始偏移坐标
if (i == endRowStart)
{
if (startAxis == Axis.Horizontal)
{
actualCellCountX = Mathf.Clamp(cellCountX, 1, endRowCount);
actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildrenCount / (float)cellsPerMainAxis));
}
else
{
actualCellCountY = Mathf.Clamp(cellCountY, 1, endRowCount);
actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildrenCount / (float)cellsPerMainAxis));
}
requiredSpace = new Vector2(
actualCellCountX * realSize.x + (actualCellCountX - 1) * spacing.x,
actualCellCountY * realSize.y + (actualCellCountY - 1) * spacing.y
);
startOffset = new Vector2(
GetStartOffset(0, requiredSpace.x),
GetStartOffset(1, requiredSpace.y)
);
}
int positionX;
int positionY;
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, startOffset.x + (realSize[0] + spacing[0]) * positionX, cellSize[0]);
SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (realSize[1] + spacing[1]) * positionY, cellSize[1]);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UI;
using UnityEngine;
[CanEditMultipleObjects]
[CustomEditor(typeof(AdapGridLayoutGroup), true)]
public class AdapGridLayoutGroupEditor : GridLayoutGroupEditor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
var compnent = target as AdapGridLayoutGroup;
compnent.austerity = EditorGUILayout.Toggle("是否紧缩", compnent.austerity);
}
}
暂未实现GridLayoutGroup根据内容进行ContentFilterSize的功能