unity ugui text 超链接和下划线,支持部分富文本格式

这篇具有很好参考价值的文章主要介绍了unity ugui text 超链接和下划线,支持部分富文本格式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

unity版本:2021.3.6f1
局限性:
1.测试发现不能使用 size 富文本标签,
2.同一文本不能设置不同颜色的超链接文本
其它:代码中注释掉使用innerTextColor的地方,可以使用富文本设置超链接颜色, 但是下划线是文本本身颜色

项目需要用到该功能, 搜索和参考了很多文章,要么不支持富文本,要不没有下划线,要么是错误的,修修改改后满足我的需求,代码如下

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

namespace MyTool.Tools
{
    /// <summary>
    /// 文本控件支持超链接、下划线
    /// </summary>
    public class HyperlinkText : Text, IPointerClickHandler
    {
        public Action<string> onHyperlinkClick;

        /// 超链接信息类
        private class HyperlinkInfo
        {
            public int startIndex;
            public int endIndex;
            public string name;
            public readonly List<Rect> boxes = new List<Rect>();
            public List<int> linefeedIndexList = new List<int>();
        }

        /// 解析完最终的文本
        private string m_OutputText;

        /// 超链接信息列表
        private readonly List<HyperlinkInfo> m_HrefInfos = new List<HyperlinkInfo>();

        /// 文本构造器
        protected StringBuilder s_TextBuilder = new StringBuilder();

        [Tooltip("超链接文本颜色")]
        [SerializeField] private Color32 innerTextColor = new Color32(36, 64, 180, 255);

        /// 超链接正则
        private static readonly Regex s_HrefRegex = new Regex(@"<href=([^>\n\s]+)>(.*?)(</href>)", RegexOptions.Singleline);

        // ugui富文本标签
        // 格式1:<b></b>  <i></i>
        private static readonly string[] _uguiSymbols1 = { "b", "i" };
        // 格式2:<color=#ffffff></color> <color=red></color>
        private static readonly string[] _uguiSymbols2 = { "color", "size" };

        public string GetHyperlinkInfo { get { return text; } }

        public override void SetVerticesDirty()
        {
            base.SetVerticesDirty();

            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();
                hrefInfo.linefeedIndexList.Clear();
                if (hrefInfo.startIndex >= toFill.currentVertCount)
                    continue;

                // 将超链接里面的文本顶点索引坐标加入到包围框
                toFill.PopulateUIVertex(ref vert, hrefInfo.startIndex);

                var pos = vert.position;
                var bounds = new Bounds(pos, Vector3.zero);
                hrefInfo.linefeedIndexList.Add(hrefInfo.startIndex);
                for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i++)
                {
                    if (i >= toFill.currentVertCount)
                        break;

                    toFill.PopulateUIVertex(ref vert, i);
                    vert.color = innerTextColor;
                    toFill.SetUIVertex(vert, i);

                    pos = vert.position;

                    bool needEncapsulate = true;

                    if (i > 4 && (i - hrefInfo.startIndex) % 4 == 0)
                    {
                        UIVertex lastV = new UIVertex();
                        toFill.PopulateUIVertex(ref lastV, i - 4);
                        var lastPos = lastV.position;

                        if (pos.x < lastPos.x && pos.y < lastPos.y) // 换行重新添加包围框
                        {
                            hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));
                            hrefInfo.linefeedIndexList.Add(i);
                            bounds = new Bounds(pos, Vector3.zero);
                            needEncapsulate = false;
                        }
                    }
                    if (needEncapsulate)
                    {
                        bounds.Encapsulate(pos); // 扩展包围框
                    }
                }
                hrefInfo.boxes.Add(new Rect(bounds.min, bounds.size));
            }

            //一个字一个字的划 效率差 而且字与字之间容易有接缝
            DrawUnderLine(toFill);
        }

        private void DrawUnderLine(VertexHelper vh)
        {
            UIVertex vert = new UIVertex();
            List<Vector3> startPosList = new List<Vector3>();
            List<Vector3> endPosList = new List<Vector3>();
            foreach (var hrefInfo in m_HrefInfos)
            {
                if (hrefInfo.startIndex >= vh.currentVertCount) continue;

                float minY = float.MaxValue;
                for (int i = hrefInfo.startIndex, m = hrefInfo.endIndex; i < m; i += 4)
                {
                    if (i >= vh.currentVertCount)
                        break;

                    if (hrefInfo.linefeedIndexList.Contains(i))
                    {
                        for (int j = 0; j < startPosList.Count; j++)
                        {
                            MeshUnderLine(vh, new Vector2(startPosList[j].x, minY), new Vector2(endPosList[j].x, minY));
                        }
                        startPosList.Clear();
                        endPosList.Clear();
                    }

                    vh.PopulateUIVertex(ref vert, i + 3);
                    startPosList.Add(vert.position);
                    vh.PopulateUIVertex(ref vert, i + 2);
                    endPosList.Add(vert.position);

                    if (vert.position.y < minY)
                    {
                        minY = vert.position.y;
                    }
                }

                for (int j = 0; j < startPosList.Count; j++)
                {
                    MeshUnderLine(vh, new Vector2(startPosList[j].x, minY), new Vector2(endPosList[j].x, minY));
                }
                startPosList.Clear();
                endPosList.Clear();
            }
        }

        private void MeshUnderLine(VertexHelper vh, Vector2 startPos, Vector2 endPos)
        {
            Vector2 extents = rectTransform.rect.size;
            var setting = GetGenerationSettings(extents);

            TextGenerator underlineText = new TextGenerator();
            underlineText.Populate("—", setting);

            IList<UIVertex> lineVer = underlineText.verts;/*new UIVertex[4];*///"_"的的顶点数组

            Vector3[] pos = new Vector3[4];
            pos[0] = startPos + new Vector2(-1f, 0);
            pos[3] = startPos + new Vector2(-1f, 4f);
            pos[2] = endPos + new Vector2(1f, 4f);
            pos[1] = endPos + new Vector2(1f, 0);


            UIVertex[] tempVerts = new UIVertex[4];
            for (int i = 0; i < 4; i++)
            {
                tempVerts[i] = lineVer[i];
                tempVerts[i].color = innerTextColor;
                tempVerts[i].position = pos[i];
            }

            vh.AddUIVertexQuad(tempVerts);
        }

        /// <summary>
        /// 获取超链接解析后的最后输出文本
        /// </summary>
        /// <returns></returns>
        protected virtual string GetOutputText(string outputText)
        {
            s_TextBuilder.Length = 0;
            m_HrefInfos.Clear();
            var indexText = 0;
            int count = 0;
            foreach (Match match in s_HrefRegex.Matches(outputText))
            {
                string appendStr = outputText.Substring(indexText, match.Index - indexText);

                s_TextBuilder.Append(appendStr);

                //空格和回车没有顶点渲染,所以要去掉
                count += appendStr.Length - appendStr.Replace(" ", "").Replace("\n", "").Length;
                //去掉富文本标签的长度
                for (int i = 0; i < _uguiSymbols1.Length; i++)
                {
                    count += appendStr.Length - appendStr.Replace($"<{_uguiSymbols1[i]}>", "").Replace($"</{_uguiSymbols1[i]}>", "").Length;
                }
                for (int i = 0; i < _uguiSymbols2.Length; i++)
                {
                    string pattern = $"<{_uguiSymbols2[i]}=(.*?)>";
                    count += appendStr.Length - Regex.Replace(appendStr, pattern, "").Length;
                    count += appendStr.Length - appendStr.Replace($"</{_uguiSymbols2[i]}>", "").Length;
                }

                int startIndex = (s_TextBuilder.Length - count) * 4;
                var group = match.Groups[1];
                var hrefInfo = new HyperlinkInfo
                {
                    startIndex = startIndex, // 超链接里的文本起始顶点索引
                    endIndex = startIndex + (match.Groups[2].Length * 4),
                    name = group.Value
                };
                m_HrefInfos.Add(hrefInfo);

                s_TextBuilder.Append(match.Groups[2].Value);
                indexText = match.Index + match.Length;
            }
            s_TextBuilder.Append(outputText.Substring(indexText, outputText.Length - indexText));
            return s_TextBuilder.ToString();
        }

        /// <summary>
        /// 点击事件检测是否点击到超链接文本
        /// </summary>
        /// <param name="eventData"></param>
        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))
                    {
                        if (onHyperlinkClick != null)
                            onHyperlinkClick.Invoke(hrefInfo.name);

                        return;
                    }
                }
            }
        }



#if UNITY_EDITOR
		//需延迟调用该方法
        private void AddVisibleBound()
        {
            int index = 0;

            foreach (var hrefInfo in m_HrefInfos)
            {
                Color color = new Color(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f), 0.2f);
                index++;
                foreach (Rect rect in hrefInfo.boxes)
                {
                    GameObject gameObject = new GameObject();
                    gameObject.name = string.Format("GOBoundBox[{0}]", hrefInfo.name);
                    gameObject.transform.SetParent(this.gameObject.transform, false);

                    RectTransform rectTransform = gameObject.AddComponent<RectTransform>();
                    rectTransform.sizeDelta = rect.size;
                    rectTransform.localPosition = new Vector3(rect.position.x + rect.size.x / 2, rect.position.y + rect.size.y / 2, 0);

                    Image image = gameObject.AddComponent<Image>();
                    image.color = color;
                    image.raycastTarget = false;
                }
            }
        }
#endif
    }
}

编辑器扩展
unity下划线,unity,windows
代码

using UnityEditor;
using UnityEngine;

namespace MyTool
{
    [CanEditMultipleObjects]
    [CustomEditor(typeof(Tools.HyperlinkText), true)]
    public class HyperlinkTextEditor : UnityEditor.UI.TextEditor
    {
        SerializedProperty _innerTextColor;

        protected override void OnEnable()
        {
            base.OnEnable();
            _innerTextColor = serializedObject.FindProperty("innerTextColor");
        }

        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();

            serializedObject.Update();
            EditorGUILayout.PropertyField(_innerTextColor, new GUIContent("Inner Text Color"));
            serializedObject.ApplyModifiedProperties();
            if (GUI.changed)
            {
                EditorUtility.SetDirty(target);
            }
        }
    }
}

Demo代码

using MyTool.Tools;
using System.Collections;
using UnityEngine;

public class Demo2 : MonoBehaviour
{
    public HyperlinkText text;
    // Start is called before the first frame update
    void Start()
    {
        //设置点击回调
        text.onHyperlinkClick = OnClickText;

        StartCoroutine(AddVisibleBound());
    }

    IEnumerator AddVisibleBound()
    {
        yield return null;
        text.AddVisibleBound();
    }

    void OnClickText(string s)
    {
        if (s == "第一段第一句")
        {
            Debug.Log($"111---{s}");
        }
        else if (s == "第二段第一句")
        {
            Debug.Log($"222---{s}");
        }
        else
        {
            Debug.Log($"333---{s}");
        }
    }
}

demo测试文本

<color=#ffffff><b><size=36>背着手踱着。</size></b></color><color=ffffff><href=第一段第一句>路上只我一个人</href></color><size=45>这一片天地好像是我的;我也像超出了平常旳自己,到了另一世界里。我爱热闹,也爱冷静;爱群居,也爱独处。像今晚上,一个人在这苍茫旳月下,什么都可以想,什么都可以不想,便觉是个自由的人。</size>白天里一定要做的事,一定要说的话,现在都可不理。<b><color=green>这是独处的妙处,我且受用这无边的荷香月色好了。</color></b>

<href=第二段第一句>曲曲折折的荷塘上面</href>,弥望旳是田田的叶子。叶子出水很高,像亭亭旳舞女旳裙。层层的叶子中间,零星地点缀着些白花,有袅娜(niǎo,nuó)地开着旳,有羞涩地打着朵儿旳;正如一粒粒的明珠,又如碧天里的星星,又如刚出浴的美人。微风过处,送来缕缕清香,仿佛远处高楼上渺茫的歌声似的。这时候叶子与花也有一丝的颤动,像闪电般,霎时传过荷塘的那边去了。叶子本是肩并肩密密地挨着,这便宛然有了一道凝碧的波痕。叶子底下是脉脉()的流水,遮住了,不能见一些颜色;而叶子却更见风致了。

<size=60>月光如流水一般,静静地泻在这一片叶子和花上。薄薄的青雾浮起在荷塘里。叶子和花仿佛在牛乳中洗过一样;又像笼着轻纱的梦。虽然是满月,天上却有一层淡淡的云,所以不能朗照;但我以为</size>这恰是到了好处——酣眠固不可少,小睡也别有风味的。月光是隔了树照过来的,高处丛生的灌木,落下参差的斑驳的黑影,峭楞楞如鬼一般;弯弯的杨柳的稀疏的倩影,却又像是画在荷叶上。塘中的月色并不均匀;但光与影有着和谐的旋律,<href=第三段>如梵婀(ē)(英语violin小提琴的译音)上奏着的名曲</href><color=red><i>荷塘的四面,远远近近,高高低低都是树,而杨柳最多。</i></color><href=第四段>这些树将一片荷塘重重围住</href>;只在小路一旁,漏着几段空隙,像是特为月光留下的。树色一例是阴阴的,乍看像一团烟雾;但杨柳的丰姿,便在烟雾里也辨得出。树梢上隐隐约约的是一带远山,只有些大意罢了。树缝里也漏着一两点路灯光,没精打采的,是渴睡人的眼。这时候最热闹的,要数树上的蝉声与水里的蛙声;但热闹是它们的,我什么也没有。

ui
unity下划线,unity,windows
效果
unity下划线,unity,windows文章来源地址https://www.toymoban.com/news/detail-771169.html

到了这里,关于unity ugui text 超链接和下划线,支持部分富文本格式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • HTML中设定下划线样式并且指定下划线长度

    今天笔者在写网页导航栏时,想要给链接加一个悬停下划线,写出来如下 HTMl: CSS:(关于其他格式的设定略,只看下划线这一段代码) 这样确实是设定下划线了,但是效果如下,看上去很难看 既然这样,那么该如何改变一下呢? 其实可以使用border-bottom来实现,代码如下

    2024年02月10日
    浏览(28)
  • css 下划线

    在 CSS 中,可以使用 \\\"text-decoration\\\" 属性来设置文本的下划线。例如: 这会使所有的段落文本都带有下划线。你也可以使用 \\\"text-decoration-style\\\" 属性来设置下划线的样式,例如实线、虚线或点线等。 你还可以使用 \\\"border-bottom\\\" 属性来设置下划线,例如: 这会在段落文本下方添加

    2024年02月12日
    浏览(23)
  • css下划线跟随导航

    2024年01月23日
    浏览(30)
  • a标签设置下划线动画

     

    2024年02月07日
    浏览(32)
  • React Native文本添加下划线

    2024年02月13日
    浏览(27)
  • Java实现驼峰、下划线互转

    Java实现驼峰、下划线互转 1.使用 Guava 实现 先引入相关依赖 1.2 下划线转驼峰 2.自定义代码转 2.1驼峰转下划线 2.2下划线转驼峰

    2024年02月12日
    浏览(28)
  • 电脑下划线在键盘上怎么打出来

    电脑下划线在键盘上怎么打出来, 可能很多人在打字的过程中都不知道如何在键盘上输入下划线的符号,本期内容就和大家详细介绍一些电脑打出下划线的方法吧。 1、电脑大键盘。大键盘区域找到右上角有个 - 线就是中横线,使用shift+- 即可输入下划线。 2、注意下划线输入

    2024年02月07日
    浏览(28)
  • 【CSS】鼠标(移入/移出)平滑(显示/隐藏)下划线

    鼠标移入内容时,下划线从 左 开始绘制到 右 侧结束 鼠标移出内容时,下划线从 左 开始擦除到 右 侧结束 我们给内容添加一个黑色背景 background: #000; 示例 效果 将黑色背景 background: #000; 替换成彩色渐变背景 background: linear-gradient(to right,#ec695c,#61c454); 示例 效果 宽度设置100个

    2024年02月09日
    浏览(39)
  • python里面单双下划线的区别

    区别: xx:公有变量,所有对象都可以访问; xxx :双下划线代表着是系统定义的名字。 __xxx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问。代表着类中的私有变量名。 _xxx:单前置下划线,私有化属性和方法,类对象和子类可以访问。不能用“from modu

    2023年04月24日
    浏览(22)
  • echarts 饼图 环形图 lable添加下划线

         

    2024年02月09日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包