C#处理Text文本行尾是特殊字符如坐标、超连接被分成两行的问题,目标是使之整体自动换行显示
具体例子如下:
-
问题描述:
图1是问题显示,图2是目标结果显示 。 -
具体实现代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class NonBreakingSpaceTextComponent : MonoBehaviour {
Text text;
static readonly string no_breaking_space = "\u00A0";
int allCount = 0;
Dictionary<string, string> TextDic = new Dictionary<string, string>();
Dictionary<int, int> setIndexs = new Dictionary<int, int>();
public string logoStr="";
public string addStr = "";
public string lastLogoStr = "";
void Awake()
{
allCount = 0;
if(logoStr=="")
{
logoStr = "[";//默认需处理标识符
}
if (addStr == "")
{
addStr = "\n";//默认需添加的字符
}
if (lastLogoStr == "")
{
lastLogoStr = "]";//默认需处理标识符
}
text = GetComponent<Text>();
text.RegisterDirtyVerticesCallback(OnTextChange);
}
string initText="";
void OnDisable()
{
allCount = 0;
setIndexs.Clear();
if (!string.IsNullOrEmpty(text.text))
{
if (initText!="" && !TextDic.ContainsKey(initText))
{
TextDic.Add(initText, text.text);
TextDic.Add(text.text, text.text);
}
}
text.CalculateLayoutInputVertical();
//Debug.Log("!!!!!!!!OnDisable!!!!!!!!!!!"+ text.text);
}
void OnTextChange()
{
if (text.text.Contains(" "))
{
text.text = text.text.Replace(" ", no_breaking_space);//去除文本空格(防止没到行尾就自动换行)
}
if (TextDic.ContainsKey(text.text))
{
text.text = TextDic[text.text];
}
else
{
if (text.text.Contains(logoStr))
{
if (initText == "")
{
initText = text.text;
}
setText();
}
}
}
void setText()
{
char arg = logoStr.ToCharArray()[0];
int num = text.text.Split(arg).Length - 1;//当前Text一共包含几个logoStr("[")
int curindex_L = 0;//当前logoStr("[")所在索引
int startIndex_L = 0;//当前logoStr("[")开始查询索引位置
int curindex_R = 0;//当前lastLogoStr("]")所在索引
int startIndex_R = 0;//当前lastLogoStr("]")开始查询索引位置
int j = 0;
while (j < num)
{
curindex_L = text.text.IndexOf(logoStr, startIndex_L);
curindex_R = text.text.IndexOf(lastLogoStr, startIndex_R);
int addL = 0;//新增的字符长度(“\n”)
if (!setIndexs.ContainsKey(curindex_L))
{
UILineInfo[] alls = text.cachedTextGeneratorForLayout.GetLinesArray();
int count = alls.Length;//当前显示label一共的行数
for (int i = 1; i < count; i++)
{
int flag = alls[i].startCharIdx;//当前显示label每行第一个字符的索引
if (curindex_L < flag && curindex_R >= flag)
{
addL = addStr.Length;
setIndexs.Add(curindex_L + addL, curindex_L);
text.text = text.text.Replace(logoStr, addStr + logoStr);
break;
}
}
}
startIndex_L = curindex_L + logoStr.Length + addL;
startIndex_R = startIndex_R + logoStr.Length + addL;
j++;
}
}
}
- 有待研究的问题:每次给text重新赋值后,text还保存上次赋值的结果,就已经调用RegisterDirtyVerticesCallback函数了,所以我在这里的处理方法是将处理过的结果都保存在Dictionary里,下次调用的时候,检查是否有处理过相同的text内容,有的话直接赋值,没有的话,重新处理。还不知道怎么在OnDisable()里清空上次赋值的结果,这个有待研究。