首页 > 手游开发 > Unity3D > Unity3D之继承Text类来实现超链接
2021
07-12

Unity3D之继承Text类来实现超链接

测试语句:打开<a href=www.idoubi.net>[逗分享]</a>
使用HyperlinkText时,需注意:只能用在单行的文本内容,如果是多行文本内容,则会导致超链接的点击位置会有偏差.
这个HyperlinkText类是我做了修改


using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

///
/// 文本控件,支持超链接,仅适用于单行的文本内容
/// 

public class HyperlinkText : Text, IPointerClickHandler { ///


    /// 超链接信息类
    /// 

private class HyperlinkInfo { public int startIndex; public int endIndex; public string name; public readonly List boxes = new List(); } ///


    /// 解析完最终的文本
    /// 

private string m_OutputText; ///


    /// 超链接信息列表
    /// 

private readonly List m_HrefInfos = new List(); ///


    /// 文本构造器
    /// 

protected static readonly StringBuilder s_TextBuilder = new StringBuilder(); [Serializable] public class HrefClickEvent : UnityEvent { } [SerializeField] private HrefClickEvent m_OnHrefClick = new HrefClickEvent(); ///


    /// 超链接点击事件
    /// 

public HrefClickEvent onHrefClick { get { return m_OnHrefClick; } set { m_OnHrefClick = value; } } ///


    /// 超链接正则
    /// 

private static readonly Regex s_HrefRegex = new Regex(@"\n\s]+)>(.*?)()", RegexOptions.Singleline); private HyperlinkText mHyperlinkText; public string GetHyperlinkInfo { get { return text; } } protected override void Awake() { base.Awake(); mHyperlinkText = GetComponent(); } protected override void OnEnable() { base.OnEnable(); mHyperlinkText.onHrefClick.AddListener(OnHyperlinkTextInfo); } protected override void OnDisable() { base.OnDisable(); mHyperlinkText.onHrefClick.RemoveListener(OnHyperlinkTextInfo); } public override void SetVerticesDirty() { base.SetVerticesDirty(); #if UNITY_EDITOR if (UnityEditor.PrefabUtility.GetPrefabType(this) == UnityEditor.PrefabType.Prefab) { return; } #endif // m_OutputText = GetOutputText(text); text = GetHyperlinkInfo; m_OutputText = GetOutputText(text); } protected override void OnPopulateMesh(VertexHelper toFill) { var orignText = m_Text; m_Text = m_OutputText; base.OnPopulateMesh(toFill); m_Text = orignText; UIVertex vert = new UIVertex(); // 处理超链接包围框 foreach (var hrefInfo in m_HrefInfos) { hrefInfo.boxes.Clear(); if (hrefInfo.startIndex >= toFill.currentVertCount) { continue; } // 将超链接里面的文本顶点索引坐标加入到包围框 toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex); var pos = vert.position; var bounds = new Bounds(pos, Vector3.zero); for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++) { if (i >= toFill.currentVertCount) { break; } toFill.PopulateUIVertex(ref vert, i); pos = vert.position; if (pos.x < bounds.min.x) // 换行重新添加包围框 { hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); bounds = new Bounds(pos, Vector3.zero); } else { bounds.Encapsulate(pos); // 扩展包围框 } } hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size)); } } ///


    /// 获取超链接解析后的最后输出文本
    /// 

/// protected virtual string GetOutputText(string outputText) { StringBuilder sb = new StringBuilder(); s_TextBuilder.Length = 0; m_HrefInfos.Clear(); var indexText = 0; foreach (Match match in s_HrefRegex.Matches(outputText)) { string str = outputText.Substring(indexText, match.Index - indexText); sb.Append(str); s_TextBuilder.Append(str); s_TextBuilder.Append("<color=blue>"); // 超链接颜色 var group = match.Groups[1]; var hrefInfo = new HyperlinkInfo { startIndex = sb.Length * 4, // 超链接里的文本起始顶点索引 endIndex = (sb.Length + match.Groups[2].Length - 1) * 4 + 1, name = group.Value }; m_HrefInfos.Add(hrefInfo); s_TextBuilder.Append(match.Groups[2].Value); s_TextBuilder.Append(""); sb.Append(match.Groups[2].Value); indexText = match.Index + match.Length; } s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText)); return s_TextBuilder.ToString(); } ///


    /// 点击事件检测是否点击到超链接文本
    /// 

/// public void OnPointerClick(PointerEventData eventData) { Vector2 lp = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, eventData.pressEventCamera, out lp); foreach (var hrefInfo in m_HrefInfos) { var boxes = hrefInfo.boxes; for (var i = 0; i < boxes.Count; ++i) { if (boxes[i].Contains(lp)) { m_OnHrefClick.Invoke(hrefInfo.name); return; } } } } ///


    /// 当前点击超链接回调
    /// 

///回调信息 private void OnHyperlinkTextInfo(string info) { Debug.Log("超链接信息:" + info); } }

最后编辑:
作者:搬运工
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。