Unity实现InputField中的敏感字变色

        收到需求:一个文本输入框用来输入文字或者编辑文字,同时能够检测出是否输入了敏感字。

        第一想法就是勾选Text的RichText,用标签的形式实现(<color=#ff0000>敏感字</color>),但是InputField会给出一个警告:Using Rich Text with input is unsupported(不支持);还有个问题,如果用标签,在删除时可能会破坏标签的完整性,如:出现"</color"的文本。

        解决方案:重写Text的OnPopulateMesh(VertexHelper vh)函数,改变指定位置的顶点颜色(UIVertex)

        原理和详细过程就不赘述了,参考文章:Unity Text关键词超链接/敏感词过滤算法 - 知乎 (zhihu.com)

        参考文章中是增加下划线和增加点击效果,我这里稍微修改下,改变字体的颜色。

        直接贴代码

//下面是keywordText脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public delegate void TextClickEvent(string str);
public delegate float CampareFunc(float a, float b);

struct Box
{
    public float minX;
    public float minY;
    public float maxX;
    public float maxY;
    public Box(float x, float y, float X, float Y)
    {
        minX = x; minY = y; maxX = X; maxY = Y;
    }
}

public class KeywordText : Text
{
    private Dictionary<string, List<Box>> keywordBox = new Dictionary<string, List<Box>>();
    protected override void OnPopulateMesh(VertexHelper toFill)
    {
        base.OnPopulateMesh(toFill);
        if (text.Length == 0) return;
        keywordBox.Clear();
        List<int> lineStart = new List<int>();
        List<int> indexMap = new List<int>();
        string dueText = DueString(text, ref indexMap);

        for (int i = 0; i < cachedTextGenerator.lineCount; i++)
        {
            if (cachedTextGenerator.lines[i].startCharIdx < text.Length)
                lineStart.Add(cachedTextGenerator.lines[i].startCharIdx);
        }
        lineStart.Add(int.MaxValue);
        List<UIVertex> vertexs = new List<UIVertex>(toFill.currentVertCount);
        for (int i = 0; i < toFill.currentVertCount; i++)
        {
            UIVertex tempVertex = new UIVertex();
            toFill.PopulateUIVertex(ref tempVertex, i);
            vertexs.Add(tempVertex);
        }

        List<KeyValuePair<int, int>> keyWordLocation = Utils.GetInstance().MatchKeyWorld(dueText);


        int nextLine = 1;
        for (int i = 0; i < keyWordLocation.Count; i++)
        {
            int startChar = keyWordLocation[i].Key;
            int endChar = keyWordLocation[i].Value;
            int curStart = startChar;
            while (lineStart[nextLine] <= indexMap[startChar]) nextLine++;
            string curKeyword = dueText.Substring(startChar, endChar - startChar + 1);

            for (int charIndex = startChar; charIndex <= endChar; charIndex++)
            {
                if (charIndex < endChar && indexMap[charIndex + 1] >= lineStart[nextLine])
                {
                    SetClickBox(vertexs, curStart, charIndex, toFill, curKeyword);
                    curStart = charIndex + 1;
                    nextLine++;
                }
            }
            SetClickBox(vertexs, curStart, endChar, toFill, curKeyword);
        }
    }

    private void SetClickBox(List<UIVertex> vertexs, int startChar, int endChar, VertexHelper toFill, string keyword)
    {
        if (endChar < startChar || (endChar + 1) * 4 > vertexs.Count)
        {
            Debug.LogWarning("关键词超出rectTransform大小范围");
            return;
        }

        //float minY = FindSuitableY(vertexs, startChar * 4, endChar * 4 + 3, (a, b) => a < b ? a : b);
        //float maxY = FindSuitableY(vertexs, startChar * 4, endChar * 4 + 3, (a, b) => a > b ? a : b);
        //float startX = vertexs[startChar * 4].position.x;
        //float endX = vertexs[endChar * 4 + 2].position.x;
        //Box curBox = new Box(startX, minY, endX, maxY);
        //if (keywordBox.ContainsKey(keyword))
        //{
        //    keywordBox[keyword].Add(curBox);
        //}
        //else
        //{
        //    List<Box> BoxList = new List<Box>();
        //    BoxList.Add(curBox);
        //    keywordBox.Add(keyword, BoxList);
        //}
        //DrawUnderLine(toFill, new Vector2(startX, minY), new Vector2(endX, minY));
        SetUVColor(vertexs, startChar * 4, endChar * 4 + 3, toFill);
    }

    private string DueString(string originalText, ref List<int> indexMap)
    {
        string resultStr = "";
        indexMap.Clear();
        for (int i = 0; i < originalText.Length; i++)
        {
            if (originalText[i] != ' ' && originalText[i] != '\n')
            {
                resultStr += originalText[i];
                indexMap.Add(i);
            }
        }
        return resultStr;
    }


    //private float FindSuitableY(List<UIVertex> vertexs, int startIndex, int endIndex, CampareFunc camp)
    //{
    //    if (endIndex < startIndex || endIndex >= vertexs.Count)
    //    {
    //        Debug.LogError("FindSuitableY传入参数错误 startIndex = " + startIndex + " endIndex = " + endIndex + "顶点数量vertexs.count = " + vertexs.Count);
    //        return 0;
    //    }
    //    float needY = vertexs[startIndex].position.y;
    //    for (int i = startIndex + 1; i <= endIndex; i++)
    //    {
    //        needY = camp(needY, vertexs[i].position.y);
    //    }
    //    return needY;
    //}

    private UIVertex vertex = new UIVertex();
    private void SetUVColor(List<UIVertex> vertexs, int startIndex, int endIndex, VertexHelper toFill)
    {
        if (endIndex < startIndex || endIndex >= vertexs.Count)
        {
            Debug.LogError("Test传入参数错误 startIndex = " + startIndex + " endIndex = " + endIndex + "顶点数量vertexs.count = " + vertexs.Count);
            return;
        }
        for (int i = startIndex; i <= endIndex; i++)
        {
            //vertexs[i].color
            toFill.PopulateUIVertex(ref vertex, i);
            vertex.color = Color.red;
            toFill.SetUIVertex(vertex, i);
        }
    }
}

修改部分

private void SetClickBox(List<UIVertex> vertexs, int startChar, int endChar, VertexHelper toFill, string keyword)
    {
        if (endChar < startChar || (endChar + 1) * 4 > vertexs.Count)
        {
            Debug.LogWarning("关键词超出rectTransform大小范围");
            return;
        }

        //float minY = FindSuitableY(vertexs, startChar * 4, endChar * 4 + 3, (a, b) => a < b ? a : b);
        //float maxY = FindSuitableY(vertexs, startChar * 4, endChar * 4 + 3, (a, b) => a > b ? a : b);
        //float startX = vertexs[startChar * 4].position.x;
        //float endX = vertexs[endChar * 4 + 2].position.x;
        //Box curBox = new Box(startX, minY, endX, maxY);
        //if (keywordBox.ContainsKey(keyword))
        //{
        //    keywordBox[keyword].Add(curBox);
        //}
        //else
        //{
        //    List<Box> BoxList = new List<Box>();
        //    BoxList.Add(curBox);
        //    keywordBox.Add(keyword, BoxList);
        //}
        //DrawUnderLine(toFill, new Vector2(startX, minY), new Vector2(endX, minY));
        SetUVColor(vertexs, startChar * 4, endChar * 4 + 3, toFill);
    }


    //private float FindSuitableY(List<UIVertex> vertexs, int startIndex, int endIndex, CampareFunc camp)
    //{
    //    if (endIndex < startIndex || endIndex >= vertexs.Count)
    //    {
    //        Debug.LogError("FindSuitableY传入参数错误 startIndex = " + startIndex + " endIndex = " + endIndex + "顶点数量vertexs.count = " + vertexs.Count);
    //        return 0;
    //    }
    //    float needY = vertexs[startIndex].position.y;
    //    for (int i = startIndex + 1; i <= endIndex; i++)
    //    {
    //        needY = camp(needY, vertexs[i].position.y);
    //    }
    //    return needY;
    //}

    private UIVertex vertex = new UIVertex();
    private void SetUVColor(List<UIVertex> vertexs, int startIndex, int endIndex, VertexHelper toFill)
    {
        if (endIndex < startIndex || endIndex >= vertexs.Count)
        {
            Debug.LogError("Test传入参数错误 startIndex = " + startIndex + " endIndex = " + endIndex + "顶点数量vertexs.count = " + vertexs.Count);
            return;
        }
        for (int i = startIndex; i <= endIndex; i++)
        {
            //vertexs[i].color
            toFill.PopulateUIVertex(ref vertex, i);
            vertex.color = Color.red;
            toFill.SetUIVertex(vertex, i);
        }
    }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UnityInputField组件可以实现用户输入并显示在界面上,但当输入内容超出了InputField的宽度和高度限制时,符串会被截断,影响用户的输入和显示效果。为了解决这个问题,我们可以让InputField的高度自适应输入的文,让文完整显示在里面。下面,本人将向大家介绍具体实现方法。 首先,在InputField组件的Inspector视图选择Text Component,在Content Size Fitter组件勾选Horizontal Fit和Vertical Fit两个选项,使InputField的尺寸能够根据所放置的文的大小,自动适应调整。接着,设置InputField的Vertical Overflow选项为“Truncate”,这样当输入内容超过InputField的高度时,将无法继续输入并显示滚动条。 其次,在代码实现自适应输入文的高度。使用Unity自带的ContentSizeFitter组件,为InputField组件的Text子物体添加ContentSizeFitter组件,并将VerticalFit选项设置为PreferredSize即可。这样当输入的文高度超过InputField的高度时,InputField会自动调整高度以适应输入文的显示,避免了文被截断的问题。 最后,需要注意的是,如果在InputField输入的文是动态生成的,则需要在代码实现Text组件的高度变化。可以使用ContentSizeFitter组件的OnRectTransformDimensionsChange()方法动态更新高度。代码实现如下: private void UpdateHeight() { var contentSizeFitter = _inputField.textComponent.GetComponent<ContentSizeFitter>(); contentSizeFitter.SetLayoutVertical(); _inputField.textComponent.rectTransform.sizeDelta = new Vector2(_inputField.textComponent.rectTransform.sizeDelta.x, contentSizeFitter.preferredHeight); } 综上所述,通过在Inspector视图和代码分别设置相应选项和方法,就可以实现Unity InputField高度自适应输入文的显示效果,提升用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值