在实际游戏开发工作,UI会给出如下图所示的需求,希望底框随文字长度变化,但又不能太长要限制在一定范围内,这时候又需要自动缩字
首先,我们要把底图的布局和文字的ContentSizeFilter组件挂载好
接下来上脚本,Text和TextMeshPro我分别写了适合各自的脚本,实现逻辑大差不差
思路的核心就是设置一个开始缩字的文本长度变量,例如文本宽度超过500时是多少个字符,以后超过这个字符就开始缩字,小于这个字符再变回来。如果单纯判断宽度再缩字,我们就再也无法将其变回来了
下面是代码,首先是用于Text组件的TextAutoSizer:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
[ExecuteInEditMode]
public class TextAutoSizer : MonoBehaviour
{
public float MaxWidth = 500f;
private int autoSizeLength; //文本多长时该缩字
private string lastText = ""; //上一次更新时的文本
private int maxFixSize;
private const int minFixSize = 24;
private Text textComponent;
private RectTransform textRectTransform;
private ContentSizeFitter contentSizeFitter = null;
private void OnEnable()
{
textComponent = GetComponent<Text>();
textRectTransform=textComponent.GetComponent<RectTransform>();
maxFixSize = textComponent.fontSize;
contentSizeFitter = GetComponent<ContentSizeFitter>();
}
private void Update()
{
if (textComponent.text != lastText)
{
lastText = textComponent.text;
if (autoSizeLength == 0)
{
if (textRectTransform.rect.width > MaxWidth)
{
autoSizeLength = textComponent.text.Length;
BestFix(true);
}
else
{
BestFix(false);
}
}
else
{
if (textComponent.text.Length > autoSizeLength)
{
BestFix(true);
}
else
{
BestFix(false);
}
}
}
}
private void BestFix(bool isFit)
{
textComponent.resizeTextForBestFit = isFit;
if (isFit)
{
textComponent.resizeTextMinSize = minFixSize;
textComponent.resizeTextMaxSize = maxFixSize;
textRectTransform.sizeDelta = new Vector2(MaxWidth, textRectTransform.sizeDelta.y);
}
if (contentSizeFitter)
{
contentSizeFitter.enabled = !isFit;
}
}
}
用于TextMeshPro组件的TMPAutoSizer:
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(TextMeshProUGUI))]
[ExecuteInEditMode]
public class TMPAutoSizer : MonoBehaviour
{
public float MaxWidth = 500f;
private int autoSizeLength; //文本多长时该缩字
private string lastText = ""; //上一次更新时的文本
private float originalFontSize; //最开始的字号
private float maxFixSize;
private const int minFixSize = 24;
private TextMeshProUGUI textComponent;
private RectTransform textRectTransform;
private ContentSizeFitter contentSizeFitter = null;
private void OnEnable()
{
textComponent = GetComponent<TextMeshProUGUI>();
textRectTransform = textComponent.GetComponent<RectTransform>();
originalFontSize = textComponent.fontSize;
maxFixSize = textComponent.fontSize;
contentSizeFitter = GetComponent<ContentSizeFitter>();
}
private void Update()
{
if (textComponent.text != lastText)
{
lastText = textComponent.text;
if (autoSizeLength == 0)
{
if (textRectTransform.rect.width > MaxWidth)
{
autoSizeLength = textComponent.text.Length;
BestFix(true);
}
else
{
BestFix(false);
}
}
else
{
if (textComponent.text.Length > autoSizeLength)
{
BestFix(true);
}
else
{
BestFix(false);
}
}
}
}
private void BestFix(bool isFit)
{
textComponent.enableAutoSizing = isFit;
if (isFit)
{
textComponent.fontSizeMin = minFixSize;
textComponent.fontSizeMax = maxFixSize;
textRectTransform.sizeDelta = new Vector2(MaxWidth, textRectTransform.sizeDelta.y);
}
else
{
textComponent.fontSize = originalFontSize;
}
if (contentSizeFitter)
{
contentSizeFitter.enabled = !isFit;
}
}
}