UGUI Text文本换行不可拆分数字,符号不可居首位

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值