UGUI-ContentSizeFitter之最简单实现maxSize限制
Posted KeepStudya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UGUI-ContentSizeFitter之最简单实现maxSize限制相关的知识,希望对你有一定的参考价值。
步骤
方法思路如下:
- 复制ContentSizeFitter源码出来,改名为
ContentSizeFitterEx
(AddComponentMenu里面的名字也需要改。) FitMode
增加枚举MaxSize- 增加序列化属性
m_MaxHorizontal
和m_MaxVertical
- 修改
HandleSelfFittingAlongAxis
增加maxSize判断 - 编写
GetMaxSize
方法 - 修改完毕替换场景里面的
ContentSizeFitter
为ContentSizeFitterEx
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
也会一直显示MaxHroizontal
和MaxVertical
属性的设置,假如我想选择了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();
最后效果如下:
以上是关于UGUI-ContentSizeFitter之最简单实现maxSize限制的主要内容,如果未能解决你的问题,请参考以下文章