Unity 使用正则表达式匹配输入框内的富文本,删除时使其整体删除

有些游戏聊天时会要发送个坐标或者道具信息之类的,一般都是用超链接做的,超链接也属于富文本,当我们按退格键时,如果删除到了超链接的内容,一般是希望能把超链接的部分作为整体一起删除的,否则看起来会有点奇怪,可以用正则表达式来匹配文本中出现的富文本,然后判断当前光标处于哪个富文本内,退格的时候直接将那一块富文本的内容全部删掉,代码如下

​
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;
using TMPro;

public class InputTest : MonoBehaviour
{
    private TMP_InputField m_ti_chat;
    private int selectionStartStringPosition = -1;
    private int selectionEndStringPosition = -1;
    private string oldValue;
    private string curValue;
    public Vector3 pos;

    public void Start()
    {
        //当选中输入框时不要高亮其中所有的内容
        m_ti_chat.onFocusSelectAll = false;
        m_ti_chat.onValueChanged.AddListener(OnValueChanged);
        m_ti_chat.onTextSelection.AddListener(OnTextSelection);
        m_ti_chat.onEndTextSelection.AddListener(OnEndTextSelection);
    }

    private void OnValueChanged(string arg0)
    {
        oldValue = oldValue == null ? arg0 : curValue;
        curValue = arg0;
    }

    private void OnEndTextSelection(string arg0, int arg1, int arg2)
    {
        selectionStartStringPosition = -1;
        selectionEndStringPosition = -1;
    }

    private void OnTextSelection(string arg0, int arg1, int arg2)
    {
        selectionStartStringPosition = arg1;
        selectionEndStringPosition = arg2;
    }

    public void Update()
    {
        // 检测是否按下了退格键
        if (Input.GetKeyDown(KeyCode.Backspace))
        {
            if (m_ti_chat.isFocused)
            {
                DeleteNearestColorTag(m_ti_chat);
            }
        }
    }

    /// <summary>
    /// 在当前输入框中插入坐标信息,默认是插在最右边
    /// </summary>
    private void AddCurPosInfo()
    {
        StringBuilder stb = new();
        stb.Append(m_ti_chat.text);
        string linkId = $"坐标_{pos.x},{pos.y},{pos.z}";
        string linkText = $"[X{pos.x},Y{pos.y},Z{pos.z}]";
        string replaceText = $"<#FF0000><link=\"{linkId}\">{linkText}</link></color> ";
        stb.Append(replaceText);
        m_ti_chat.text = stb.ToString();
        //选中输入框
        m_ti_chat.Select();
        //光标移到最右边
        m_ti_chat.MoveTextEnd(false);
    }

    /// <summary>
    /// 删除富文本中的内容时使其一整块整体删除
    /// </summary>
    /// <param name="inputField"></param>
    void DeleteNearestColorTag(TMP_InputField inputField)
    {
        int stringPosition = inputField.stringPosition;
        string text = curValue;
        if (selectionEndStringPosition != -1)
        {
            stringPosition = selectionEndStringPosition + 1;
            text = oldValue;
        }
        else
        {
            stringPosition += 1;
        }

        // 正则表达式匹配颜色标签及其内部的文本
        string pattern = @"<#[A-Fa-f0-9]{6}>(.*?)<\/color>";
        MatchCollection matches = Regex.Matches(text, pattern);

        // 从光标位置开始向前查找最近的匹配项
        int closestIndex = -1;
        int minDistance = int.MaxValue;
        int startIndex = 0;
        for (var index = 0; index < matches.Count; index++)
        {
            var matchTemp = matches[index];
            int distance = stringPosition - matchTemp.Index;
            if (distance >= 0 && distance < minDistance)
            {
                minDistance = distance;
                closestIndex = matchTemp.Index;
                startIndex = index;
            }
        }

        RemoveMatchText(inputField, closestIndex, matches, startIndex, stringPosition, text);
    }

    /// <summary>
    /// 删除匹配的文本
    /// </summary>
    /// <param name="inputField"></param>
    /// <param name="closestIndex"></param>
    /// <param name="matches"></param>
    /// <param name="startIndex"></param>
    /// <param name="stringPosition"></param>
    /// <param name="text"></param>
    private void RemoveMatchText(TMP_InputField inputField, int closestIndex, MatchCollection matches, int startIndex,
        int stringPosition, string text)
    {
        // 如果找到了匹配项,删除它
        if (closestIndex == -1)
        {
            return;
        }

        var match = matches[startIndex];
        // 判断光标是否在标签内
        if (stringPosition < match.Index || stringPosition > match.Index + match.Length + 1)
        {
            return;
        }

        int length = match.Length;
        int selectionLength = selectionStartStringPosition - selectionEndStringPosition;
        if (selectionStartStringPosition == -1)
        {
            inputField.text = text.Remove(closestIndex, length);
            inputField.caretPosition = closestIndex; // 移动光标到删除标签后的位置
        }
        else
        {
            if (selectionLength > 0)
            {
                length = selectionStartStringPosition - closestIndex;
                inputField.text = text.Remove(closestIndex, length);
                inputField.caretPosition = closestIndex; // 移动光标到删除标签后的位置
            }
            else
            {
                inputField.text = text.Remove(selectionStartStringPosition, match.Index + match.Length + 1 - selectionStartStringPosition);
                inputField.caretPosition = selectionStartStringPosition; // 移动光标到删除标签后的位置
            }
        }
    }
}

​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
正则表达式(Regular Expression)是一种用于匹配和处理文本的强大工具,它在很多编程语言中都有广泛应用,包括Unity。在Unity中,可以使用正则表达式来进行字符串的匹配、替换、提取等操作。 Unity使用正则表达式语法与其他编程语言中的语法基本相同,常见的用法包括: 1. 匹配字符串:使用正则表达式可以判断一个字符串是否符合某种模式。例如,可以使用正则表达式`"hello"`来匹配字符串中是否包含"hello"这个单词。 2. 替换字符串:使用正则表达式可以将字符串中符合某种模式的部分替换为指定的内容。例如,可以使用正则表达式`"\\d+"`来匹配字符串中的数字,并将其替换为指定的内容。 3. 提取信息:使用正则表达式可以从字符串中提取出符合某种模式的部分。例如,可以使用正则表达式`"\\w+"`来提取字符串中的单词。 在Unity中,可以使用`System.Text.RegularExpressions.Regex`类来进行正则表达式的操作。该类提供了一系列静态方法,如`Match`、`Matches`、`Replace`等,用于执行正则表达式的匹配、替换等操作。 下面是一些相关问题: 1. Unity中如何使用正则表达式进行字符串匹配? 2. 如何在Unity使用正则表达式进行字符串替换? 3. Unity中如何提取字符串中符合某种模式的部分? 4. 有没有一些常用的正则表达式示例在Unity中的应用场景? 5. Unity中的正则表达式是否支持大小写敏感? 6. 如何处理正则表达式中的特殊字符?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值