【狂雲歌之unity_vr】unity裏獲取text中文字寬度並截斷省略

【狂雲歌之unity_vr】unity裏獲取text中文字寬度並截斷省略

unityvr

前言

 在unity的ugui中Text控件,有時咱們會有各類各樣的需求,好比相似html中css的text-overflow屬性,但願一段文字若是不夠長就全顯示,若是特別長就截斷而且後面加上例如...這種後綴。css

 好吧這樣的需求在ugui裏貌似沒有現成的方法,若是有的話麻煩指點一下~html

實現

 大概的思路就是dom

  • 首先要能判斷何時overflow字體

  • 而且支持加上後綴ui

 那麼text控件原本是支持overflow而後直接截斷的,可是比較暴力,直接砍斷,不能加後綴,並不知足咱們的需求。this

 而後若是簡單的經過字符個數截斷,那根本不行,若是根據中英文字符來根據長度截斷,這個我試過,然而字體並不必定是一箇中文至關於倆英文字符,因而乎若是有一大排lllll或者iii什麼的,悲劇無以言表。spa

 因此咱們須要知道一段文字所對應的渲染以後的長度。若是從text的preferwidth或者經過添加content size filter組件應該也能完成相似任務,不過我傾向於直接算好長度去填充。.net

 這個功能核心代碼爲code

Font myFont = text.font;  //chatText is my Text component
myFont.RequestCharactersInTexture(message, text.fontSize, text.fontStyle);
CharacterInfo characterInfo = new CharacterInfo();

char[] arr = message.ToCharArray();

foreach (char c in arr)
{
    myFont.GetCharacterInfo(c, out characterInfo, text.fontSize);

    totalLength += characterInfo.advance;
}

 其中text爲Text文本控件,RequestCharactersInTexture主要至關於指定須要渲染哪些字符(而後根據CharacterInfo.characterInfo是能夠拿到本次生成的去重後的字符集)。接下來經過myFont.GetCharacterInfo(c, out characterInfo, text.fontSize);分別去得到每一個字符的信息,而後characterInfo.advance就拿到了每一個字符的渲染長度。component

 拿到每一個字符長度以後那就簡單多了,計算一下須要截斷的字符總長度,若是大於限制長度,就除去後綴長度後,截取子字符串,而後再接上後綴。這個事情就搞定了。

效果以下:

out

所有以下,這個例子是須要一個text和一個button,點擊button,隨機生成文字在text上。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;

public class TextWidth : MonoBehaviour {
    public Text text;
    public Button button;
    const string suffix = "...";
    const int MAX_WIDTH = 200;
    int suffixWidth = 0;
    string[] seeds = { "是都", "60°", "qの", "【】" , "d a", "as", "WW", "II", "fs", "as", "WW", "II", "fs" };
    // Use this for initialization
    void Start () {
        Init();
        button.onClick.AddListener(Rand);
    }

    void Init()
    {
        //計算後綴的長度
        suffixWidth = CalculateLengthOfText(suffix);
        Debug.Log("suffixWidth : " + suffixWidth);
    }

    string StripLengthWithSuffix(string input, int maxWidth = MAX_WIDTH)
    {
        int len = CalculateLengthOfText(input);
        Debug.Log("input total length = " + len);
        //截斷text的長度,若是總長度大於限制的最大長度,
        //那麼先根據最大長度減去後綴長度的值拿到字符串,在拼接上後綴
        if (len > maxWidth)
        {
            return StripLength(input, maxWidth - suffixWidth) + suffix;
        }else
        {
            return input;
        }
    }

    //隨機生成個字符串
    void Rand()
    {
        int min = 12;
        int max = 16;
        int num = (int)(Random.value * (max - min) + min);

        Debug.Log("-------------------------\n num : " + num);
        string s = "";
        for (int j = 0; j < num; j++)
        {
            int len = seeds.Length;
            int index = (int)(Random.value * (len));
            s += seeds[index];
        }
        Debug.Log("s : " + s);
        text.text = StripLengthWithSuffix(s);
        Debug.Log("StripLength " + text.text);
    }

    /// <summary>
    /// 根據maxWidth來截斷input拿到子字符串
    /// </summary>
    /// <param name="input"></param>
    /// <param name="maxWidth"></param>
    /// <returns></returns>
    string StripLength(string input, int maxWidth = MAX_WIDTH)
    {
        int totalLength = 0;
        Font myFont = text.font;  //chatText is my Text component
        
        myFont.RequestCharactersInTexture(input, text.fontSize, text.fontStyle);
        
        CharacterInfo characterInfo = new CharacterInfo();

        char[] arr = input.ToCharArray();

        int i = 0;
        foreach (char c in arr)
        {
            myFont.GetCharacterInfo(c, out characterInfo, text.fontSize);

            int newLength = totalLength + characterInfo.advance;
            if (newLength > maxWidth)
            {
                Debug.LogFormat("newLength {0},  totalLength {1}: ", newLength, totalLength);
                if (Mathf.Abs(newLength - maxWidth) > Mathf.Abs(maxWidth - totalLength)){
                    break;
                }else
                {
                    totalLength = newLength;
                    i++;
                    break;
                }
            }
            totalLength += characterInfo.advance;
            i++;
        }
        Debug.LogFormat("totalLength {0} : ", totalLength);
        return input.Substring(0, i);
    }

    /// <summary>
    /// 計算字符串在指定text控件中的長度
    /// </summary>
    /// <param name="message"></param>
    /// <returns></returns>
    int CalculateLengthOfText(string message)
    {
        int totalLength = 0;
        Font myFont = text.font;  //chatText is my Text component
        myFont.RequestCharactersInTexture(message, text.fontSize, text.fontStyle);
        CharacterInfo characterInfo = new CharacterInfo();

        char[] arr = message.ToCharArray();

        foreach (char c in arr)
        {
            myFont.GetCharacterInfo(c, out characterInfo, text.fontSize);

            totalLength += characterInfo.advance;
        }

        return totalLength;
    }

}

後續

這個效果基本達到要求,若是仔細看的話,並不能保證每一個截取後的字符串必定是對齊的,這個也跟字符串有關,畢竟字符串長度是離散的,貌似沒有辦法像word同樣在一行多一個文字的時候還能夠擠一擠放下~

VR開發或者unity相關交流能夠郵件madcloudsong@qq .com
轉載請註明原文連接
http://blog.csdn.net/madcloud...

相關文章
相關標籤/搜索