Unityでは標準機能で"テキストの長さに応じて表示範囲を広げる"ということはできるのですが、デフォルトのUI表示を崩したくないこともしばしばあります。
そこで表示範囲はそのままに、表示範囲を超える長いテキストが入っているときには"テキストが省略されている"ということを伝えられる機能を作りました。
ソースコード
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コンポーネントと一緒にアタッチしておくだけ。
実装の解説
アタッチするだけでリアルタイムに処理ができるのはGraphic.UnregisterDirtyLayoutCallback
のおかげです。こいつにイベントを登録すると、Text.textのsetが呼ばれたタイミングでコールバックを受け取ることができます。便利。
範囲を超えたら〜の部分は、
- Textの変数としても用意されている
TextGenerator
を利用して文字数を取得 - 文字数に達するまで1文字目から順番にテキストを形成していく
- 必要表示範囲を超えたら、1つ前の文字を省略記号(...)に変えて表示させる
となっています。