C#处理Text文本行尾是特殊字符如坐标、超连接被分成两行的问题,目标是使之整体自动换行显示

本文介绍了一个C#代码示例,用于解决Unity中Text组件在遇到坐标、超链接等特殊字符导致行尾换行不正确的问题。通过使用非断行空格替换空格,并维护一个字典来存储已处理过的文本,实现了整体自动换行显示。文章还提出了在OnDisable()方法中清除上次赋值结果的待研究问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C#处理Text文本行尾是特殊字符如坐标、超连接被分成两行的问题,目标是使之整体自动换行显示

具体例子如下:

  1. 问题描述:
    图1
    图2
    图1是问题显示,图2是目标结果显示 。

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

  1. 有待研究的问题:每次给text重新赋值后,text还保存上次赋值的结果,就已经调用RegisterDirtyVerticesCallback函数了,所以我在这里的处理方法是将处理过的结果都保存在Dictionary里,下次调用的时候,检查是否有处理过相同的text内容,有的话直接赋值,没有的话,重新处理。还不知道怎么在OnDisable()里清空上次赋值的结果,这个有待研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值