using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.UI;
public class TextTest : MonoBehaviour
{
public Text m_CompText;
private StringBuilder sb = new StringBuilder();
private float rectWidth;
private readonly bool UseWrapCondition = true;//数字不可拆分换行,符号不可居首位
private readonly int DiffNum = 2; // 首行数字或符号个数误差范围内,将字符们提到上一行显示
private bool _isUseWrapCondition = false;
private void Awake()
{
const float ScreenScale = 1f; // 屏幕与初始设定分辨率的比,直观上是画布的Scale值
rectWidth = m_CompText.rectTransform.rect.width * ScreenScale;
_isUseWrapCondition = UseWrapCondition && m_CompText.horizontalOverflow == HorizontalWrapMode.Wrap;
}
public void SetTextContent(string content)
{
m_CompText.text = content;
if (_isUseWrapCondition)
{
m_CompText.horizontalOverflow = HorizontalWrapMode.Wrap;
if (this.gameObject.activeInHierarchy)
{
StopCoroutine("CheckWarpCondition");
StartCoroutine("CheckWarpCondition");
}
}
}
// charWidth受画布Scale影响
WaitForEndOfFrame wait = new WaitForEndOfFrame();
List<int> lineChangedList = new List<int>();
private System.Collections.IEnumerator CheckWarpCondition()
{
yield return wait;
int strLength = m_CompText.text.Length;
if (strLength <= 2) yield break;
if (m_CompText.cachedTextGenerator.lineCount <= 1) yield break;
m_CompText.horizontalOverflow = HorizontalWrapMode.Overflow;
lineChangedList.Clear();
int index = m_CompText.text.IndexOf("\n");
while (index >= 0 && index < strLength)
{
lineChangedList.Add(index);
index = m_CompText.text.IndexOf("\n", index + 1);
}
sb.Clear();
float lineWidth = 0f, numWidth = 0f, lastCharWidth = 0f;
int numStartIndex = -1, sbEndIndex = -1;
bool isDigit = false, isSymbol = false;
char _char;
for (int i = 0; i < Mathf.Min(m_CompText.cachedTextGenerator.characterCount, strLength); i++)
{
if (sbEndIndex >= 0 && i <= sbEndIndex) continue;
_char = m_CompText.text[i];
UICharInfo item = m_CompText.cachedTextGenerator.characters[i];
if (item.charWidth == 0)
{
sb.Append(_char);
if (lineChangedList.Count > 0 && i >= lineChangedList[0])
{
lineChangedList.RemoveAt(0);
lineWidth = numWidth = lastCharWidth = 0f;
numStartIndex = sbEndIndex = -1;
}
continue;
}
isDigit = char.IsDigit(_char);
isSymbol = isDigit ? false : char.IsSymbol(_char) || char.IsPunctuation(_char);
if (isDigit || isSymbol)
{
if (numStartIndex == -1)
{
numStartIndex = sb.Length;
}
numWidth += item.charWidth;
}
else if (numStartIndex >= 0)
{
numStartIndex = -1;
numWidth = 0f;
}
if (lineWidth > 0 && lineWidth + item.charWidth > rectWidth)// 从当前字符开始,超框了
{
if (!isDigit && !isSymbol)
{
sb.Append("\n");
sb.Append(_char);
lineWidth = item.charWidth;
}
else if (NextLineDiffValid(m_CompText.cachedTextGenerator.characters, i, out int endIndex, out float width, isSymbol))
{
sbEndIndex = endIndex;
sb.Append(m_CompText.text, i, endIndex - i + 1);
if (sbEndIndex >= strLength - 1)
break;
if (lineChangedList.Count > 0 && sbEndIndex >= lineChangedList[0])
lineChangedList.RemoveAt(0);
else
sb.Append("\n");
lineWidth = 0;
}
else
{
sbEndIndex = endIndex;
if (numStartIndex>= 0)
{
if (isDigit)
sb.Insert(numStartIndex, "\n");
else if (numStartIndex > 0)
sb.Insert(numStartIndex - 1, "\n");
lineWidth = numWidth + width;
}
else
{
sb.Insert(sb.Length - 1, "\n");
lineWidth = lastCharWidth;
}
sb.Append(m_CompText.text, i, endIndex - i + 1);
}
}
else
{
sb.Append(_char);
lastCharWidth = item.charWidth;
lineWidth += lastCharWidth;
}
}
m_CompText.text = sb.ToString();
sb.Clear();
lineChangedList.Clear();
}
// 判断下一行文本开头的数字或符号的字符数是否符合偏差数量,out 输出符号或数字的尾号
private bool NextLineDiffValid(IList<UICharInfo> characters, int startIndex, out int endIndex, out float width, bool isSymbol)
{
endIndex = startIndex;
width = 0;
if (DiffNum > 0)
{
bool _symbol;
char _char;
UICharInfo item;
int count = 0, len = Mathf.Min(characters.Count, m_CompText.text.Length);
if (startIndex == len - 1)
return count <= DiffNum - 1;
for (int i = startIndex + 1; i < len; i++)
{
item = characters[i];
_char = m_CompText.text[i];
if (item.charWidth > 0)
{
_symbol = char.IsSymbol(_char) || char.IsPunctuation(_char);
if ((isSymbol && !_symbol) || (!_symbol && !char.IsDigit(_char)))
{
endIndex = i - 1;
return count <= DiffNum - 1;
}
width += item.charWidth;
count++;
}
else if (_char == '\n')
{
endIndex = i;
return count <= DiffNum - 1;
}
endIndex = i;
if (i == len - 1)
return count <= DiffNum - 1;
}
}
return false;
}
}
UGUI Text文本换行不可拆分数字,符号不可居首位
于 2024-03-29 12:02:57 首次发布