项目中碰到文字超过显示区域的情况,Unity UGUI没有类似css的自动省略号,产品希望能展示全,考虑可以做个滚动文字的组件。
目前实现两种滚动方式:来回滚动和从左到右再回到最左边,都是循环滚动,逻辑不复杂,参考代码。
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Mask))]
[RequireComponent(typeof(Image))]
public class AutoRollText : MonoBehaviour
{
public enum RollType
{
Pingpong = 0,
Left = 1
}
public RollType rollType = RollType.Pingpong;
public Text m_text;
[Header("延迟时间")] public float delay = 5f;
[Header("移动速度")] public float speed = .1f;
[Header("边界检测允许差值")] public float limitDiff = 5f;
private float _textWidth;
private RectTransform _rect;
public string text
{
set
{
m_text.text = value;
CalcTextPos();
}
get { return m_text.text; }
}
private void Awake()
{
_rect = this.transform as RectTransform;
if (m_text == null)
{
m_text = this.GetComponentInChildren<Text>(true);
}
m_text.rectTransform.pivot = new Vector2(0, 0.5f);
// m_text.rectTransform.anchoredPosition = new Vector2(-_rect.sizeDelta.x / 2, 0);
CalcTextPos();
}
private void CalcTextPos()
{
// 根据字数 调整 view 宽度
TextGenerator generator = new TextGenerator();
TextGenerationSettings settings = m_text.GetGenerationSettings(Vector2.zero);
_textWidth = generator.GetPreferredWidth(text, settings);
Vector2 size = m_text.rectTransform.sizeDelta;
size.x = _textWidth;
m_text.rectTransform.sizeDelta = size;
Vector2 pos = new Vector2(-size.x / 2, 0);
pos.x += (_textWidth - _rect.sizeDelta.x) / 2f;
Debug.Log($"textWidth:{_textWidth}-----width:{_rect.sizeDelta.x}-----pos:{pos}");
m_text.rectTransform.anchoredPosition = pos;
StopCoroutine(nameof(RollCoroutine));
if (_textWidth > _rect.sizeDelta.x) //文字超出大小
{
StartCoroutine(nameof(RollCoroutine));
}
}
private IEnumerator RollCoroutine()
{
Vector2 pos = m_text.rectTransform.anchoredPosition;
Vector2 current = pos;
float offset = _textWidth - _rect.sizeDelta.x;
if (delay > 0)
{
yield return new WaitForSeconds(delay);
}
switch (rollType)
{
case RollType.Pingpong:
{
bool leftDir = true;
while (true)
{
if (leftDir)
{
current.x -= speed;
}
else
{
current.x += speed;
}
m_text.rectTransform.anchoredPosition = current;
if (current.x < (pos.x - offset - limitDiff))
{
leftDir = false;
}
else if (current.x >= pos.x + limitDiff)
{
leftDir = true;
}
yield return null;
}
}
break;
case RollType.Left:
{
while (true)
{
current.x -= speed;
m_text.rectTransform.anchoredPosition = current;
yield return null;
if (current.x < (pos.x - offset - limitDiff))
{
yield return new WaitForSeconds(delay);
current.x = pos.x;
m_text.rectTransform.anchoredPosition = current;
if (delay > 0)
{
yield return new WaitForSeconds(delay);
}
}
}
}
break;
}
}
}
组件分为两层结构,父层是一个mask,移动出去的文字超出显示区域不显示,子层是文字,如下:
文字显示的区域为父层RectTransform的Size。
参考工程:https://github.com/eangulee/CustomUGUI.git