LoginSignup
10
10

More than 5 years have passed since last update.

【Unity】範囲内に収まらないテキストを省略表示する

Posted at

Unityでは標準機能で"テキストの長さに応じて表示範囲を広げる"ということはできるのですが、デフォルトのUI表示を崩したくないこともしばしばあります。
そこで表示範囲はそのままに、表示範囲を超える長いテキストが入っているときには"テキストが省略されている"ということを伝えられる機能を作りました。

screenshot.gif

ソースコード

【GitHub】TextEllipsis

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class UITextEllipsis : UIBehaviour
{
    private Text m_Text;

    protected override void Awake()
    {
        if (m_Text != null)
        {
            return;
        }

        m_Text = GetComponent<Text>();
        m_Text.RegisterDirtyLayoutCallback(DoEllipsis);
    }

    protected override void OnDestroy()
    {
        m_Text.UnregisterDirtyLayoutCallback(DoEllipsis);
    }

    private static readonly string ELLIPSIS = "...";

    private void DoEllipsis()
    {
        if (!IsActive() || m_Text == null)
        {
            return;
        }

        if (!NeedsEllipsis(m_Text))
        {
            return;
        }

        TextGenerator generator = m_Text.cachedTextGenerator;
        TextGenerationSettings settings = m_Text.GetGenerationSettings(m_Text.rectTransform.rect.size);
        generator.Populate(m_Text.text, settings);
        string result = string.Empty;
        for (int i = 0; i < generator.characterCount; ++i)
        {
            string current = m_Text.text.Substring(i, 1);
            string next = string.Empty;
            if (i + 1 <= generator.characterCount)
            {
                next = m_Text.text.Substring(i + 1, 1);
            }

            var preferredWidth = GetPreferredWidth(result + current + next);
            if (IsOverSize(m_Text.rectTransform.rect.size.x, preferredWidth))
            {
                result += ELLIPSIS;
                break;
            }

            result += current;
        }

        m_Text.text = result;
    }

    private bool NeedsEllipsis(Text text)
    {
        return IsOverSize(text.rectTransform.rect.size.x, text.preferredWidth);
    }

    private bool IsOverSize(float textBoxWidth, float preferredWidth)
    {
        return textBoxWidth < preferredWidth;
    }

    private float GetPreferredWidth(string str)
    {
        var settings = m_Text.GetGenerationSettings(Vector2.zero);
        return m_Text.cachedTextGeneratorForLayout.GetPreferredWidth(str, settings) / m_Text.pixelsPerUnit;
    }
}

使い方

Textコンポーネントと一緒にアタッチしておくだけ。

screenshot.png

実装の解説

アタッチするだけでリアルタイムに処理ができるのはGraphic.UnregisterDirtyLayoutCallbackのおかげです。こいつにイベントを登録すると、Text.textのsetが呼ばれたタイミングでコールバックを受け取ることができます。便利。

範囲を超えたら〜の部分は、
1. Textの変数としても用意されているTextGeneratorを利用して文字数を取得
2. 文字数に達するまで1文字目から順番にテキストを形成していく
3. 必要表示範囲を超えたら、1つ前の文字を省略記号(...)に変えて表示させる
となっています。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10