获得Text中文本尺寸的方法有两种:
(1)比较笨的方法是,预先计算出每个字符的尺寸,比如“Oh我的Baby”这句话,想要知道他的物理尺寸,需要知道每个英文字符的物理尺寸和每个中文字的物理尺寸。可以预先将26个英文字符都测量一下(包括大写字符),中文字符基本上就等于Text.FontSize的尺寸,将这些尺寸数据存到Json文件中,然后解析获得配置字典。然后解析这句歌词。将他转化成字符遍历,依次分割每个单词和每个中文字符,分割之时计算每个单词和每个中文字符的尺寸。每个单词每个字符的尺寸计算出来之后就可以计算出整句话的长度了。
附上一段代码:
核心的思路是:遍历每个字符,执行如下操作:
(1)判断当前字符若是中文字符if (sentence[i] >= 0x4e00 && sentence[i] <= 0x9fbb)
就将他划分成一个字符并将他的尺寸记录到perFontSizeCach
集合中,同时要看该字符之前是否有字符,若有字符判断该字符是空格、是中文字符还是英文字符,若是空格或者中文字符就不管,若是英文字符就将前面累计的尺寸perFontLen
的字符划分为一个单词,同时将累计尺寸perFontLen
放到perFontSizeCache
中。此外要把标记前一个字符是中文字符的布尔变量preCharIsChinese
置true
;
(2)若当前字符不是中文字符,那么判断当前字符是否被包含在配置字典中LyricsManager.Instance.CharToSizeMap
,如果该字符不包含在配置字典中,就认为他是一个单词的一部分,他的尺寸都统一默认按48处理,累加到perFontLen
上。若该字符被包含在该字典中,那么就判断preCharIsChinese
是否true
,若为true即前一个字符是中文字符那么就认为当前字符是属于当前字符的一部分,获得他的尺寸并添加到累加尺寸上perFontLen += LyricsManager.Instance.CharToSizeMap[sentence[i].ToString()];
如果前一个字符是非中文字符,那么判断是否属于一句话的第一个字符、前一个字符是否为空格及当前字符是否为空格,若满足上述三种情况,那么就认为之前的字符串为一个单词,进行分割,将之前累加的字符尺寸perFontLen
添加到每个字尺寸缓存perFontSizeCache
中perFontSizeCach.Add(perFontLen);
,此外此时要将当前的空格尺寸视为是下一个字的一部分,将它的尺寸累加perFontLen = LyricsManager.Instance.CharToSizeMap[" "];
,最后需要将前一个字符是中文字符变量preCharIsChinese
置false
。
(3)最后在每次遍历最后都要判断是否是最后一个字符,及前一个字符是否是中文字符,若是最后一个字符,且前一个字符不是中文字符,那么就将前面累加字符添加到perFontSizeCache
中perFontSizeCach.Add(perFontLen);
。因为在最后一个字为英文单词可能没法划分为一个字,用这种方法来维持一致性。
totalSize = 0;
bool preCharIsChinese = false;
float perFontLen = 0;
perFontSizeCach.Clear();
for (int i = 0; i < sentence.Length; i++)
{
if (sentence[i] >= 0x4e00 && sentence[i] <= 0x9fbb)
{//根据Unicode编码知在这个范围内的字符为中文字符
if (i > 0 && sentence[i - 1] != ' ' && preCharIsChinese == false)
{
//分割前面的为一个英文字
perFontSizeCach.Add(perFontLen);
perFontLen = 0;
}
perFontLen += text.fontSize;
perFontSizeCach.Add(perFontLen);
preCharIsChinese = true;
perFontLen = 0;
}
else
{
if (LyricsManager.Instance.CharToSizeMap.ContainsKey(sentence[i].ToString()))
{//这个字典中就是记录着每个字符的物理尺寸
if (preCharIsChinese == false)
{
if (i > 0 && sentence[i - 1] != ' ' && sentence[i] == ' ')
{
//分割前面的为一个英文字
perFontSizeCach.Add(perFontLen);
perFontLen = 0;
perFontLen = LyricsManager.Instance.CharToSizeMap[" "];
}
else
{
perFontLen += LyricsManager.Instance.CharToSizeMap[sentence[i].ToString()];
}
}
else
{
perFontLen += LyricsManager.Instance.CharToSizeMap[sentence[i].ToString()];
}
}
else
{
perFontLen += text.fontSize;
}
preCharIsChinese = false;
}
if (i == sentence.Length - 1 && preCharIsChinese == false)
{
perFontSizeCach.Add(perFontLen);
perFontLen = 0;
}
}
(2)另一种方法是比较先进的方法,直接利用Text组件中的给定的API来求得。我们知道Text中有Font引用,在该引用中包含有该Text引用的字体,其实一个字符串也就是放到一个Font中,通过Font将他渲染到对应的纹理上以显示出来的。而Text只是提供了一种间接管理的作用。从接收字符串,然后传给Font文本字符串及一些其他的比如字体尺寸、字体风格等参数,然后Font将把字体渲染出来。Font中包含了很多属性和方法以便于进行显示处理。
在该处首先获得Text的Font实例。我们想要获得一个文本的尺寸,那么就需要先将文本渲染到纹理上Font.RequestCharactersInTexture()
,这样Font上才会包含该文本数据。在Font中文本是按照一个一个字符绘制的,所以也应该按照一个一个字符去取到每个字符的信息CharacterInfo
。在每个字符信息中包含有当前字符的尺寸CharacterInfo.advance
,由此将每个字符的尺寸相加便可得出文本的尺寸。
Font sentenceFont = text.font;//获得Font的实例
sentenceFont.RequestCharactersInTexture(sentence, 48, text.fontStyle);//先将文本绘制出来,
//由此处可以看出影响文本绘制的因素很多,有字体尺寸和字体风格等
CharacterInfo fontInfo;
char[] arr = sentence.ToCharArray();
for (int i = 0; i < arr.Length; i++)
{
sentenceFont.GetCharacterInfo(arr[i], out fontInfo, 48);//根据字符获取字符的信息
totalSize += fontInfo.advance;//将字符尺寸累加
}