unity GridLayoutGroup真正的居中

news2024/9/22 13:33:56

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);
            }
        }
    }
}

效果:

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2100252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将语义分割的标签转换为实例分割(yolo)的标签

语义分割的标签&#xff08;目标处为255&#xff0c;其余处为0&#xff09; 实例分割的标签&#xff08;yolo.txt&#xff09;,描述边界的多边形顶点的归一化位置 绘制在原图类似蓝色的边框所示。 废话不多说&#xff0c;直接贴代码&#xff1b; import os import cv2 imp…

【高阶数据结构】二叉树的创建、存储方式(顺序与链式)、遍历方法(递归与非递归)(精美图解+完整代码)

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《高阶数据结构》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多《高阶数据结构》点击专栏链接查看&a…

单体到微服务:架构变迁

单体架构与微服务架构&#xff1a;从单体到微服务的演变 引言单体架构概述微服务架构的优势一、功能定位二、使用场景三、配置方式四、性能特点Eureka - 服务注册与发现框架核心功能工作原理优势应用场景 结论 引言 在软件开发的世界中&#xff0c;随着业务的增长和技术的发展…

RabbitMQ 基础架构流程 数据隔离 创建用户

介绍 publisher&#xff1a;消息发送者-exchange&#xff1a;交换机&#xff0c;复制路由的消息-queue&#xff1a;队列&#xff0c;存储消息consumer&#xff1a;消息的消费者 工作流程 publisher消息发送者 -> exchange 交换机 -> queue 队列 -> consumer 消息的消…

关于CUDA版本查看的问题

显卡驱动安装成功后&#xff0c;通过nvidia-smi命令查看显卡信息 右上角显示的CUDA Version&#xff1a;12.1并非本机的 CUDA 版本&#xff0c;而是 GPU 最高支持的 CUDA 版本&#xff0c;本机安装的CUDA版本不能高于GPU最高支持的版本。 通过nvcc --version查看到的版本才是本…

SprinBoot+Vue图书管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

MapBox Android版开发 3 地图样式v11

MapBox Android版开发 3 地图样式v11 前言MapBox样式对比主要类和方法Style类Style类默认的MapBox样式OnStyleLoaded 接口 MapboxMap类获取样式设置样式 本地化扩展 示例代码地图样式类界面布局控件响应事件运行效果图 附不同样式中的图层 前言 可以使用Mapbox Maps SDK自定义…

LLM大模型教程:低使用门槛开源大模型服务框架Ollama

这一年来&#xff0c;AI 发展的越来越快&#xff0c;大模型使用的门槛也越来越低&#xff0c;每个人都可以在自己的本地运行大模型。今天再给大家介绍一个最厉害的开源大模型服务框架——Ollama。 项目介绍 Ollama 是一个开源的大语言模型&#xff08;LLM&#xff09;服务工具…

平价运动耳机推荐有哪些?业界五大爆款推荐!

近两年&#xff0c;开放式蓝牙耳机的热度可以说是不断提高&#xff0c;相较于一般的蓝牙耳机&#xff0c;开放式蓝牙耳机因为不需要入耳&#xff0c;对于耳道狭小或者耳道敏感的人群比较友好&#xff0c;能够避免耳道不适、中耳炎等&#xff0c;长时间佩戴更舒适&#xff0c;适…

【一嗨租车-注册安全分析报告-滑动验证加载不正常导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

大模型时代,开发者怎么办

随着ChatGPT的出圈&#xff0c;基于大模型开发的应用也不断涌现&#xff0c;不管是不是相关方向的从业人员&#xff0c;在这一年多总能听到很多新名词&#xff0c;从LLM、Prompt、RAG到Fine-tuning、Agent&#xff0c;各个大企业都在讲All in AI&#xff0c;一些技术会议也明显…

Massive Exploration of Neural Machine Translation Architectures论文解读

基本信息 作者D Britzdoi发表时间2017期刊EMNLP网址https://arxiv.org/abs/1703.03906v1 研究背景 1. What’s known 既往研究已证实 神经机器翻译NMT是一种自动翻译的端到端方法&#xff08;Neural Machine Translation by Jointly Learning to Align and Translate论文里的…

Gartner《2024中国安全技术成熟度曲线》AI安全助手代表性产品:开发者安全助手D10

海云安关注到&#xff0c;近日&#xff0c;国际权威研究机构Gartner发布了《2024中国安全技术成熟度曲线》(Hype Cycle for Security in China,2024)报告。 在此次报告中&#xff0c;安全技术成熟度曲线将安全周期划分为技术萌芽期&#xff08;Innovation Trigger&#xff09;…

快捷开发技巧-idea如何提取代码成方法

1.首选选中要抽取的代码段 2.右键选择Refactor->Extract Method 3.调整方法名称 4.回车保存

Find My资讯|腾势联名九号推出F2 升级版电动滑板车,支持苹果Find My功能

比亚迪腾势与九号电动推出的联名电动滑板车 F2 升级版已在腾势商城上架&#xff0c;该车支持苹果“Find My”查找功能&#xff0c;续航里程 40 公里&#xff0c;售价为 2999 元。 该车配备 30 毫米双筒减振&#xff0c;采用 10 英寸自修复果冻胎&#xff0c;拥有前碟刹 后 E…

改变地址栏的网址链接路径或传参,不刷新当前网页页面

window.history.replaceState(null, null, "/网址后面的路径?参数参数值1");window.history.replaceState(null, null, "./当前路径保留?参数参数值1");

linux 系统中关于文件压缩效率/压缩比的说明

前言 tar.gz&#xff08;或tgz&#xff09;格式是Linux中常用的压缩格式&#xff0c;它结合了tar的打包功能和gzip的压缩功能。根据搜索结果&#xff0c;tar.gz格式在压缩比率、压缩和解压速度上取得了较好的平衡。 在一项测试中&#xff0c;一个大约23GB的目录使用tar.gz格式…

win7一键修复所有dll缺失!全面介绍电脑DLL文件丢失修复过程!

在Windows 7操作系统中&#xff0c;DLL&#xff08;动态链接库&#xff09;文件扮演着至关重要的角色。它们是Windows系统和其他应用程序正常运行所必需的组件。然而&#xff0c;由于各种原因&#xff0c;如系统更新不当、软件卸载不完全或恶意软件攻击&#xff0c;DLL文件可能…

线性结构队列栈知识点(软件设计师)

线性结构 1.线性表2.线性表存储结构顺序存储链式存储 3.栈4.队列5.串 1.线性表 线性表是最简单、最基本的数据结构。线性表常采用顺序存储和链式存储&#xff0c;主要的基本操作是插入、删除和查找等 2.线性表存储结构 顺序存储 插入、删除 移动元素查找时间复杂度O(1) 可以随…

极简的go语言channel入门

写在文章开头 很久没写go语言相关的文章了&#xff0c;近期准备整理整理go语言channel相关的知识点&#xff0c;而本文将通过几个示例快速带读者了解channel的基本概念&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 ja…