unity GridLayoutGroup真正的居中

GridLayoutGroup默认的居中效果:

  

不是真正的居中 加上代码:
namespace UnityEngine.UI
{
    /// <summary>
    /// GridLayoutGroup拓展,使支持自定义内容
    /// </summary>
    internal class GridLayoutGroupEx : GridLayoutGroup
    {
        /// <summary>
        /// 启用居中
        /// </summary>
        bool m_enableMiddle = true;
        /// <summary>
        /// 超过行数采用默认的
        /// </summary>
        int m_surpassLine = 2;

        public bool EnableMiddle
        {
            set { m_enableMiddle = value; }
            get { return m_enableMiddle; }
        }

        public int SurpassLine
        {
            set { m_surpassLine = value; }
            get { return m_surpassLine; }
        }

        /// <summary>
        /// Called by the layout system
        /// Also see ILayoutElement
        /// </summary>
        public override void SetLayoutHorizontal()
        {
            SetCellsAlongAxis(0);
        }

        /// <summary>
        /// Called by the layout system
        /// Also see ILayoutElement
        /// </summary>
        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.

            if (axis == 0)
            {
                // Only set the sizes when invoked for horizontal axis, not the positions.
                for (int i = 0; i < rectChildren.Count; 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 (rectChildren.Count > cellCountX)
                    cellCountY = rectChildren.Count / cellCountX + (rectChildren.Count % cellCountX > 0 ? 1 : 0);
            }
            else if (m_Constraint == Constraint.FixedRowCount)
            {
                cellCountY = m_ConstraintCount;

                if (rectChildren.Count > cellCountY)
                    cellCountX = rectChildren.Count / cellCountY + (rectChildren.Count % 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, rectChildren.Count);
                actualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis));
            }
            else
            {
                cellsPerMainAxis = cellCountY;
                actualCellCountY = Mathf.Clamp(cellCountY, 1, rectChildren.Count);
                actualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildren.Count / (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)
            );

            int customActualCellCountX, customActualCellCountY;
            if (startAxis == Axis.Horizontal)
            {
                customActualCellCountX = rectChildren.Count % cellCountX;
                customActualCellCountY = Mathf.Clamp(cellCountY, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis));
            }
            else
            {
                customActualCellCountY = rectChildren.Count % cellCountY;
                customActualCellCountX = Mathf.Clamp(cellCountX, 1, Mathf.CeilToInt(rectChildren.Count / (float)cellsPerMainAxis));
            }
            Vector2 customRequiredSpace = new Vector2(
                customActualCellCountX * cellSize.x + (customActualCellCountX - 1) * spacing.x,
                customActualCellCountY * cellSize.y + (customActualCellCountY - 1) * spacing.y
            );
            Vector2 customStartOffset = new Vector2(
                GetStartOffset(0, customRequiredSpace.x),
                GetStartOffset(1, customRequiredSpace.y)
            );

            //Debug.Log("actualCellCountX: " + actualCellCountX);
            //Debug.Log("actualCellCountY: " + actualCellCountY);
            //Debug.Log("requiredSpace.x: " + requiredSpace.x);
            //Debug.Log("requiredSpace.y: " + requiredSpace.y);
            //Debug.Log("startOffset.x: " + startOffset.x);
            //Debug.Log("startOffset.y: " + startOffset.y);
            //Debug.Log("-------------------------------");
            //Debug.Log("customActualCellCountX: " + customActualCellCountX);
            //Debug.Log("customActualCellCountY: " + customActualCellCountY);
            //Debug.Log("customRequiredSpace.x: " + customRequiredSpace.x);
            //Debug.Log("customRequiredSpace.y: " + customRequiredSpace.y);
            //Debug.Log("customStartOffset.x: " + customStartOffset.x);
            //Debug.Log("customStartOffset.y: " + customStartOffset.y);

            int startCount = rectChildren.Count % cellsPerMainAxis;
            int totalLine = startAxis == Axis.Horizontal ? customActualCellCountY : customActualCellCountX;
            for (int i = 0; i < rectChildren.Count; i++)
            {
                int positionX;
                int positionY;

                if (m_enableMiddle && startCount > 0 && totalLine <= m_surpassLine)
                {
                    if (i < startCount)
                    {
                        if (startAxis == Axis.Horizontal)
                        {
                            positionX = i;
                            positionY = 0;

                            if (cornerX == 1)
                                positionX = startCount - 1 - positionX;
                            if (cornerY == 1)
                                positionY = actualCellCountY - 1 - positionY;
                        }
                        else
                        {
                            positionX = 0;
                            positionY = i;

                            if (cornerX == 1)
                                positionX = actualCellCountX - 1 - positionX;
                            if (cornerY == 1)
                                positionY = startCount - 1 - positionY;
                        }

                        SetChildAlongAxis(rectChildren[i], 0, customStartOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
                        SetChildAlongAxis(rectChildren[i], 1, customStartOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
                    }
                    else
                    {
                        int index = i - startCount;
                        if (startAxis == Axis.Horizontal)
                        {
                            positionX = index % cellsPerMainAxis;
                            positionY = index / cellsPerMainAxis + 1;
                        }
                        else
                        {
                            positionX = index / cellsPerMainAxis + 1;
                            positionY = index % cellsPerMainAxis;
                        }

                        if (cornerX == 1)
                            positionX = actualCellCountX - 1 - positionX;
                        if (cornerY == 1)
                            positionY = actualCellCountY - 1 - positionY;

                        SetChildAlongAxis(rectChildren[i], 0, startOffset.x + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
                        SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
                    }
                }
                else
                {
                    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 + (cellSize[0] + spacing[0]) * positionX, cellSize[0]);
                    SetChildAlongAxis(rectChildren[i], 1, startOffset.y + (cellSize[1] + spacing[1]) * positionY, cellSize[1]);
                }

                //Debuger.Log("positionX: " + positionX + "positionY: " + positionY + ",cellsPerMainAxis: " + cellsPerMainAxis);
            }
        }
    }
}

效果:

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值