UGUI-ContentSizeFitter之最简单实现maxSize限制

news2024/11/17 3:34:26

步骤

方法思路如下:

  1. 复制ContentSizeFitter源码出来,改名为ContentSizeFitterEx (AddComponentMenu里面的名字也需要改。)
  2. FitMode增加枚举MaxSize
  3. 增加序列化属性m_MaxHorizontalm_MaxVertical
  4. 修改HandleSelfFittingAlongAxis增加maxSize判断
  5. 编写GetMaxSize方法
  6. 修改完毕替换场景里面的ContentSizeFitterContentSizeFitterEx

ContentSizeFitterEx完整源码

复制到项目里面任意位置即可

using System.Collections.Generic;
using UnityEngine.EventSystems;

namespace UnityEngine.UI
{
    internal static class SetPropertyUtility
    {
        public static bool SetColor(ref Color currentValue, Color newValue)
        {
            if (currentValue.r == newValue.r && currentValue.g == newValue.g && currentValue.b == newValue.b &&
                currentValue.a == newValue.a)
                return false;

            currentValue = newValue;
            return true;
        }

        public static bool SetStruct<T>(ref T currentValue, T newValue) where T : struct
        {
            if (EqualityComparer<T>.Default.Equals(currentValue, newValue))
                return false;

            currentValue = newValue;
            return true;
        }

        public static bool SetClass<T>(ref T currentValue, T newValue) where T : class
        {
            if ((currentValue == null && newValue == null) || (currentValue != null && currentValue.Equals(newValue)))
                return false;

            currentValue = newValue;
            return true;
        }
    }


    [AddComponentMenu("Layout/Content Size Fitter Ex", 141)]
    [ExecuteAlways]
    [RequireComponent(typeof(RectTransform))]
    /// <summary>
    /// Resizes a RectTransform to fit the size of its content.
    /// </summary>
    /// <remarks>
    /// The ContentSizeFitter can be used on GameObjects that have one or more ILayoutElement components, such as Text, Image, HorizontalLayoutGroup, VerticalLayoutGroup, and GridLayoutGroup.
    /// </remarks>
    public class ContentSizeFitterEx : UIBehaviour, ILayoutSelfController
    {
        /// <summary>
        /// The size fit modes avaliable to use.
        /// </summary>
        public enum FitMode
        {
            /// <summary>
            /// Don't perform any resizing.
            /// </summary>
            Unconstrained,

            /// <summary>
            /// Resize to the minimum size of the content.
            /// </summary>
            MinSize,

            MaxSize,

            /// <summary>
            /// Resize to the preferred size of the content.
            /// </summary>
            PreferredSize
        }

        [SerializeField] protected FitMode m_HorizontalFit = FitMode.Unconstrained;
        [SerializeField] protected int m_MaxHorizontal = 900;
        [SerializeField] protected int m_MaxVertical = 100;

        /// <summary>
        /// The fit mode to use to determine the width.
        /// </summary>
        public FitMode horizontalFit
        {
            get { return m_HorizontalFit; }
            set
            {
                if (SetPropertyUtility.SetStruct(ref m_HorizontalFit, value)) SetDirty();
            }
        }

        [SerializeField] protected FitMode m_VerticalFit = FitMode.Unconstrained;

        /// <summary>
        /// The fit mode to use to determine the height.
        /// </summary>
        public FitMode verticalFit
        {
            get { return m_VerticalFit; }
            set
            {
                if (SetPropertyUtility.SetStruct(ref m_VerticalFit, value)) SetDirty();
            }
        }

        [System.NonSerialized] private RectTransform m_Rect;

        private RectTransform rectTransform
        {
            get
            {
                if (m_Rect == null)
                    m_Rect = GetComponent<RectTransform>();
                return m_Rect;
            }
        }

        // field is never assigned warning
#pragma warning disable 649
        private DrivenRectTransformTracker m_Tracker;
#pragma warning restore 649

        protected ContentSizeFitterEx()
        {
        }

        protected override void OnEnable()
        {
            base.OnEnable();
            SetDirty();
        }

        protected override void OnDisable()
        {
            m_Tracker.Clear();
            LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
            base.OnDisable();
        }

        protected override void OnRectTransformDimensionsChange()
        {
            SetDirty();
        }

        private void HandleSelfFittingAlongAxis(int axis)
        {
            FitMode fitting = (axis == 0 ? horizontalFit : verticalFit);
            if (fitting == FitMode.Unconstrained)
            {
                // Keep a reference to the tracked transform, but don't control its properties:
                m_Tracker.Add(this, rectTransform, DrivenTransformProperties.None);
                return;
            }

            m_Tracker.Add(this, rectTransform,
                (axis == 0 ? DrivenTransformProperties.SizeDeltaX : DrivenTransformProperties.SizeDeltaY));

            // Set size to min or preferred size
            if (fitting == FitMode.MinSize)
            {
                rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis,
                    LayoutUtility.GetMinSize(m_Rect, axis));
            }
            else if (fitting == FitMode.MaxSize)
            {
            	//增加maxSize判断返回
                rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis, GetMaxSize(m_Rect, axis));
            }
            else
            {
                rectTransform.SetSizeWithCurrentAnchors((RectTransform.Axis)axis,
                    LayoutUtility.GetPreferredSize(m_Rect, axis));
            }
        }
		
		/// <summary>
        /// 增加maxSize获取
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="axis"></param>
        /// <returns></returns>
        private float GetMaxSize(RectTransform rect, int axis)
        {
            var size = axis == 0 ? LayoutUtility.GetPreferredWidth(rect) : LayoutUtility.GetPreferredHeight(rect);

            if (axis == 0)
            {
                if (size > m_MaxHorizontal)
                {
                    return m_MaxHorizontal;
                }
            }
            else
            {
                if (size > m_MaxVertical)
                {
                    return m_MaxVertical;
                }
            }

            return size;
        }


        /// <summary>
        /// Calculate and apply the horizontal component of the size to the RectTransform
        /// </summary>
        public virtual void SetLayoutHorizontal()
        {
            m_Tracker.Clear();
            HandleSelfFittingAlongAxis(0);
        }

        /// <summary>
        /// Calculate and apply the vertical component of the size to the RectTransform
        /// </summary>
        public virtual void SetLayoutVertical()
        {
            HandleSelfFittingAlongAxis(1);
        }

        protected void SetDirty()
        {
            if (!IsActive())
                return;

            LayoutRebuilder.MarkLayoutForRebuild(rectTransform);
        }

#if UNITY_EDITOR
        protected override void OnValidate()
        {
            SetDirty();
        }

#endif
    }
}

效果

在这里插入图片描述

优化Editor使用

当上面的操作改完之后发现我不选MaxSize也会一直显示MaxHroizontalMaxVertical属性的设置,假如我想选择了MaxSize的时候才显示配置呢? 增加ContentSizeFitterExEditor类即可,注意该类需要放到Editor目录下,例如我是这样子放的:
在这里插入图片描述

using UnityEngine;
using UnityEngine.UI;

namespace UnityEditor.UI
{
    [CustomEditor(typeof(ContentSizeFitterEx), true)]
    [CanEditMultipleObjects]
    /// <summary>
    /// Custom Editor for the ContentSizeFitter Component.
    /// Extend this class to write a custom editor for a component derived from ContentSizeFitter.
    /// </summary>
    public class ContentSizeFitterExEditor : SelfControllerEditor
    {
        SerializedProperty m_HorizontalFit;
        SerializedProperty m_VerticalFit;
		//增加Max配置
        SerializedProperty m_MaxHorizontal;
        SerializedProperty m_MaxVertical;

        protected virtual void OnEnable()
        {
            m_HorizontalFit = serializedObject.FindProperty("m_HorizontalFit");
            m_VerticalFit = serializedObject.FindProperty("m_VerticalFit");
			//增加属性获取
            m_MaxHorizontal = serializedObject.FindProperty("m_MaxHorizontal");
            m_MaxVertical = serializedObject.FindProperty("m_MaxVertical");
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            EditorGUILayout.PropertyField(m_HorizontalFit, true);
            EditorGUILayout.PropertyField(m_VerticalFit, true);

			//判断选择了第二个MaxSize才显示max设置
            if (m_HorizontalFit.enumValueIndex == 2)
            {
                EditorGUILayout.PropertyField(m_MaxHorizontal);
            }
            //判断选择了第二个MaxSize才显示max设置
            if (m_VerticalFit.enumValueIndex == 2)
            {
                EditorGUILayout.PropertyField(m_MaxVertical);
            }

            serializedObject.ApplyModifiedProperties();

            base.OnInspectorGUI();
        }
    }
}

最后效果如下:
在这里插入图片描述

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

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

相关文章

智能商业化模式:信息流广告的动态展现策略

丨目录&#xff1a; 摘要 引言 问题建模 实验 总结与展望 关于我们 参考文献▐ 摘要大多数的信息流场景会向用户展现自然内容和商业化内容&#xff08;广告&#xff09;的混合结果。一种比较常见的做法是&#xff0c;将广告限定在固定位置进行展现&#xff0c;但由于这种静态广…

7 常用类实例

常用类 1 object类 类的声明&#xff1a;public class object 类所属的包&#xff1a;java.lang object是所有类的根类Java中的所有类&#xff0c;如果没有特殊说明&#xff0c;则默认继承object object的派生类对象都可以调用这些方法&#xff0c;派生类一般会对根据需要重…

2022最新CKA认证指南看这里

目录 &#x1f9e1;CKA简介 &#x1f9e1;CKA报名 &#x1f9e1;注意事项 &#x1f9e1;题目 &#x1f49f;这里是CS大白话专场&#xff0c;让枯燥的学习变得有趣&#xff01; &#x1f49f;没有对象不要怕&#xff0c;我们new一个出来&#xff0c;每天对ta说不尽情话&…

代码随想录——二叉树

二叉树遍历 基本介绍&#xff1a; 二叉树主要有两种遍历方式&#xff1a; 深度优先遍历&#xff1a;先往深走&#xff0c;遇到叶子节点再往回走。【前中后序遍历】广度优先遍历&#xff1a;一层一层的去遍历。【层序遍历】 这两种遍历是图论中最基本的两种遍历方式 深度优…

录制电脑内部声音,2个方法,轻松解决

在我们日常的学习、娱乐和工作中&#xff0c;我们经常会遇到需要使用电脑录屏的情况。在电脑录屏的时候&#xff0c;怎么录制电脑内部声音&#xff1f;今天小编分享2个方法&#xff0c;教你如何轻松解决这个问题&#xff0c;一起来看看吧。 录制电脑内部声音方法1&#xff1a;Q…

Python基于PyTorch实现BP神经网络ANN分类模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 在人工神经网络的发展历史上&#xff0c;感知机(Multilayer Perceptron&#xff0c;MLP)网络曾对人工神…

什么是真正的骨传导耳机,五款真骨传导耳机推荐

市面上真假骨传导耳机不能辨别&#xff1f;真骨传导耳机是没有喇叭传播声音的&#xff0c;通过振子传播声音&#xff0c;我们在区分耳机是不是真骨传导耳机时&#xff0c;可以看看机身有没有喇叭音孔&#xff0c;有音孔的就不是利用骨传导传播声音的方式&#xff0c;下面就给大…

新的AI技术展望

“科学史是克服我们自身认知局限的不懈动力。”——约翰克拉考尔 这些是关于未来人工智能的话语。现在你可能在想&#xff0c;人工智能将如何影响我们&#xff0c;我们将如何处理它&#xff1f; 不用担心; 我有一个答案。AI&#xff08;人工智能&#xff09;已经在很多方面影…

easyexcel案例之类型转换,合并单元格,批注,下拉框,导入校验

文章目录easyexcel案例之类型转换&#xff0c;合并单元格&#xff0c;批注&#xff0c;下拉框&#xff0c;导入校验一、依赖二、导出1.类型转换导出2.自定义文件标题3.合并单元格导出注解方式通过 registerWriteHandler 方法注册进去自定义合并规则进行合并4.批注和下拉框导出批…

vulnhub DC系列 DC-2

总结:cewl和wpscan的使用&#xff0c;rbash逃逸&#xff0c;suid提权 下载地址 DC-2.zip (Size: 847 MB)Download: http://www.five86.com/downloads/DC-2.zipDownload (Mirror): https://download.vulnhub.com/dc/DC-2.zip使用方法:解压后&#xff0c;使用vm直接打开ova文件 漏…

MergeTree原理之二级索引

二级索引 除了一级索引之外&#xff0c;MergeTree同样支持二级索引&#xff0c;二级索引又称跳数索引&#xff0c;由数据的聚合信息构建而成。根据索引类型的不同&#xff0c;其聚合信息的内容也不同&#xff0c;当然跳数索引的作用和一级索引是一样的&#xff0c;也是为了查询…

【SpringCloud】什么是微服务?什么是SpringCloud?

【SpringCloud】什么是微服务&#xff1f;什么是SpringCloud&#xff1f; 一、什么是微服务&#xff1f; 1. 微服务架构的演变历程 单体架构 单体架构优缺点 2. 分布式架构 分布式架构优缺点 存在问题 3. 微服务 微服务的架构特征 微服务的优缺点 二、SpringClo…

头部3D建模新应用:护目镜类产品定制,省时高效好选择

自从越来越多人开始了运动健身&#xff0c;不少运动爱好者已经从小白用户升级为高级运动玩家。随着大家对运动装备的要求也越来越高&#xff0c;不少爱好者开始选购一些轻量化的私人订制装备。例如&#xff0c;高度符合用户头部外型的游泳眼镜、骑行护目镜等等。 游泳眼镜是为了…

用ACLS去控制访问文件

ACLs可以针对多个用户以及群组&#xff0c;其他人做出权限控制。文件系统需要挂载被ACL支持。XFS文件系统支持ACL。EXt4在7版本中默认激活ACL.但在更早的版本需要使用acl选项去挂载申请。 上图第十个字符.代表已经有了acl.表示已经设置ALC。文件的owner可以对文件设置ACL. get…

【结构型】组合模式(Composite)

目录组合模式(Composite)适用场景组合模式实例代码&#xff08;Java&#xff09;组合模式(Composite) 将对象组合成树型结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 适用场景 想表示对象的部分-整体层次结构。希望用户忽略…

Java判断null的几种方式

组内code review时&#xff0c;有同学提到字符串判断空值的写法&#xff0c;如下两种&#xff0c;&#xff08;1&#xff09;null在后&#xff0c;Test public void testDemo1() {String str null;if (str null) {System.out.println("null在后");return;} }&#…

计算机的人机交互

1、 计算机的人机交互发展历史 计算机在刚开始出现的时候&#xff0c;因为占地广、造价高、耗电高的原因&#xff0c;一般都是给军队、政府使用的&#xff0c;并不是给个人使用的。随着计算机的发展&#xff0c;体积越来越小&#xff0c;出现了微型机&#xff0c;才使得计算机…

C# 数据库 ADO.NET概述

一 数据库 1 数据库&#xff08;Database&#xff09; 2 数据库管理系统&#xff08;DBMS&#xff09; 如Oracle,MS SQL Server 3 数据库系统的优点 共享性、独立性、完整性、冗余数据少。 4 管理功能 数据定义/操纵/完整/完全/并发 二 常用的数据库管理系统 1 微软的…

剑指offer----C语言版----第二天

目录 1. 二维数组中的查找 1.1 题目描述 1.1 思路一 1.2 思路二 1.3 思路三&#xff08;最优解&#xff09; 1. 二维数组中的查找 原题链接&#xff1a;剑指 Offer 04. 二维数组中的查找 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/er-wei-shu-…

WinServer 2012 域控组策略 用户发布软件部署

本例演示安装 Notepad 这款软件 因为域中发布软件只支持 msi 格式&#xff0c;所以要把 exe 转成 msi 格式&#xff0c;可以用这个软件 https://www.advancedinstaller.com/ 1、转换格式 &#xff08;1&#xff09;选择 MSI from EXE &#xff08;2&#xff09;定义项目名…