原因 当字符串中带有半角空格,且半角空格后面的字符串内容超过文本剩余显示宽度时,Text组件会将后面的整段文字做换行。这个并不是bug,而是Text组件按照拉丁西语的分词习惯做line break,半角空格相当于分隔符,分隔空格前后的内容,并视之为单词。这种分词规则在西语中是正确的,但用在中文就水土不服了:整段的中文内容,粗暴地按半角空格分成了3部分,第一行空格后面的大段文字被判定为一个单词,剩余宽度无法显示,就被整个换到了第二行。
解决方案 解决原理很简单,如果碰到首字符是标点符号,那么就提前一个字符或者多个字符让他换行就可以了。 如果对中文排版要求比较高,就要考虑自己动手做Text的布局实现了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 using System.Collections;using System.Collections.Generic;using System.Text;using System.Text.RegularExpressions;using UnityEngine;using UnityEngine.UI;[RequireComponent(typeof(Text)) ] public class TextFit : MonoBehaviour { private readonly string strRegex = @"\p{P}" ; private System.Text.StringBuilder MExplainText = null ; private IList<UILineInfo> MExpalinTextLine; public IEnumerator MClearUpExplainMode (string _text ) { _text = _text.Replace(" " , "" ); _text = _text.Replace("\t" , "" ); _text = _text.Replace(" " , "" ); if (_text[0 ] != '\u3000' ) { _text = "\u3000\u3000" + _text; _text = _text.Replace("\n" , "\n\u3000\u3000" ); } Text _component = transform.GetComponent<Text>(); _component.text = _text; yield return new WaitForSeconds (0.001f ) ; MExpalinTextLine = _component.cachedTextGenerator.lines; int mChangeIndex = 0 ; bool Is_H = false ; MExplainText = new System.Text.StringBuilder(_component.text); for (int i = 1 ; i < MExpalinTextLine.Count; i++) { if (_component.text.Length > MExpalinTextLine[i].startCharIdx) { bool _b = Regex.IsMatch(_component.text[MExpalinTextLine[i].startCharIdx ].ToString(), strRegex); if (_b) { int DD = 1 ; while (true ) { bool _bb = Regex.IsMatch(_component.text[MExpalinTextLine[i].startCharIdx - DD].ToString(), strRegex); if (!_bb) { Is_H = true ; mChangeIndex = MExpalinTextLine[i].startCharIdx - 1 ; MExplainText.Insert(mChangeIndex - (DD - 1 ), "\n" ); _component.text = MExplainText.ToString(); StartCoroutine(MClearUpExplainMode(MExplainText.ToString())); break ; } else { DD++; } } if (Is_H) break ; } } } _component.text = MExplainText.ToString(); } }
使用方法 1 2 var textFit = gameObject.GetComponent<TextFit>(); StartCoroutine(textFit.MClearUpExplainMode(info));