惠州做棋牌网站建设哪家好,预装wordpress主机,西安活动公司,安徽省质量提升工程建设网站一、带富文本标签的框选是什么
UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition#xff0c;开始选择时的光标下标和当前光标下标 对于未添加富文本标签时#xff0c;直接通过以上两个值#xff0c;判断一下框选方向#xff08;前向后/后向前…一、带富文本标签的框选是什么
UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition开始选择时的光标下标和当前光标下标 对于未添加富文本标签时直接通过以上两个值判断一下框选方向前向后/后向前进而对inputfield的text内容进行字符串拆分即可
相关基础内容可以看一些参考博客
https://blog.51cto.com/u_15296378/7884559 但是对于有富文本标签的inputfield这两个值返回的只是表面看起来的索引并没有包含富文本标签。 举个栗子
对于一段普通文本未添加富文本今天没有下雨
你想选择“没有下”那么索引应该是2和4 但是对于一段富文本内容今天b没有/b下雨
你想选择“没有下”那么真实索引应该是5和12
那么根据实际索引拆分后的字符串是这样“没有/b下” 然而你再使用selectionAnchorPosition和selectionFocusPosition尝试获取时依然得到的是2和4
那么根据原索引拆分后的字符串是这样“b”就完全被富文本标签干扰了 截止目前还没有或者我没找到官方直接可以使用的支持带有富文本标签的框选或选中内容定位获取接口。因此只能自己计算 二、获取真实富文本标签定位的大致思路
为了获取真实定位这里我们先不考虑框选先只考虑一个字符的位置。
还是以今天b没有/b下雨为例
我想获取“没”的真实定位只需要在原索引加上其前面富文本标签“b”的长度即可
那么2就变成了5 进而扩展一下今天bicoloryellow没有/color/i/b下雨 对于这个文本
想获取“没”的真实定位就需要将“没”前面所有富文本标签的长度都加上 那么写一个方法去除目标索引前的第一个富文本标签并记录去除后的字符串和被去除标签的字符数量然后递归调用自己直到没有富文本标签之后结束 计算框选时第二个字的定位时也是同理这里后面框选时计算的调节稍有不同下文讲 如果想要返回的内容中不包含富文本标签类似上图中的打印结果只要“车10辆”三个字那么使用一个正则字符串替换即可 //移除选定部分所有富文本标签public string RemoveRichTextTags(string text) {return System.Text.RegularExpressions.Regex.Replace(text, .*?, string.Empty);} 三、代码实现
在unity创建RichTextTagHandler类
这里先假定只有一个InputField被编辑无切换 先创建一个全局变量用来保存某次计算的真实索引
private int total 0; 创建RemoveFrontRichTag方法用于移除指定字符串目标索引前第一个富文本标签
/// summary
/// 从前往后移除第一个富文本标签计数标签字符数量并将移除后的字符串返回
/// /summary
/// param nameaimString待移除富文本标签的目标字符串/param
/// param namesurfaceIndex原定位/param
/// param namecount用来计数用的 标记已经移除的富文本标签字符长度/param
/// returns阶段性返回当前移除的富文本标签字符数量递归后最终返回所有符合要求的富文本标签字符总数量/returns
private string RemoveFrontRichTag(string aimString,int surfaceIndex, ref int count) {//先尝试定位int meet aimString.IndexOf();//如果定位不到或者定位超过了原支付长度说明标签在我们所选字符后面或者无富文本标签了方法直接返回并将数量count设置为0if (meet -1 || meet surfaceIndex) {count 0;return aimString;}//成功定位到‘’后继续定位‘’int leave aimString.IndexOf();//将字符串拆分成去掉及其内部内容string newString aimString.Substring(0, meet) aimString.Substring(leave 1, aimString.Length - leave - 1);//计算去掉部分的字符数量int length leave - meet 1;count length;//Debug.Log(newString meet meet leave leave length length);//把去掉已计数的标签后的字符串返回return newString;
} 创建TryGetRealIndex方法用于递归调用移除目标索引前的所有富文本标签
/// summary
/// 尝试获取真实索引递归方法
/// /summary
/// param namerichText/param
/// param namesurfaceIndex/param
/// param nameisEndPoint/param
/// returns/returns
private int TryGetRealIndex(string richText, int surfaceIndex,bool isEndPoint) {string newString richText;int count 0;//先尝试定位‘’并获取它的定位int mark newString.IndexOf();//-1是没找到没找到或大于原本的定位那么代表原本定位之前已经没有了直接返回结束if ((isEndPoint (mark -1 || mark surfaceIndex)) || //如果是结尾的点那么判断mark时添加等号防止后侧遗留标签整体(!isEndPoint (mark -1 || mark surfaceIndex))) {//如果不是结尾的点那么判断mark时不加等号判断前侧遗留标签整体return total;}//如果在原定位前找到了那么走一遍清除最前的富文本标签并计数的方法else {//清除一次标签并将清除后的字符串保存newString RemoveFrontRichTag(newString, surfaceIndex, ref count);//加入计数total count;//回调继续判断原本定位前是否有富文本标记TryGetRealIndex(newString, surfaceIndex, isEndPoint);}//递归完成后返回最终的富文本标签字符总数return total;
} 最后创建GetRealIndex用于获取最终索引并返回
/// summary
/// 获取选定部分排除富文本标签后富文本标签也算作数量字符的真实位置
/// /summary
/// param nameinputField/param
/// param namesurfaceIndex/param
/// param nameisEndPoint
/// 默认为false从选定位置往前所有富文本标签全部排除通常为选定部分的“前面”点
/// 传入true后从选定位置开始不仅往前而且往后所有富文本标签全部排除通常为选定部分“后面”点
/// 注意选定时从前往后选和从后往前选“前面”和“后面”的点要判断一下
/// 扩展如果“前面”点传入true而“后面”点传入false那么可以获取选定区域开始前后所有的富文本标签都会被选定默认是清除前后所有富文本标签
/// /param
/// returns/returns
public int GetRealIndex(TMP_InputField inputField, int surfaceIndex,bool isEndPointfalse) {//string richText inputField.text;//所有surfaceIndex前富文本标签所占的字符总数int allRichTagCharCount 0;total 0;//每次开始前重置total为0//递归获取富文本标签所占的字符总数allRichTagCharCount TryGetRealIndex(richText, surfaceIndex,isEndPoint);//最终实际的定位是富文本字符总数与surfaceIndex表定位的合return allRichTagCharCount surfaceIndex;
}
完整的脚本长这样
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class RichTextTagHandler {private int total 0;/// summary/// 获取选定部分排除富文本标签后富文本标签也算作数量字符的真实位置/// /summary/// param nameinputField/param/// param namesurfaceIndex/param/// param nameisEndPoint/// 默认为false从选定位置往前所有富文本标签全部排除通常为选定部分的“前面”点/// 传入true后从选定位置开始不仅往前而且往后所有富文本标签全部排除通常为选定部分“后面”点/// 注意选定时从前往后选和从后往前选“前面”和“后面”的点要判断一下/// 扩展如果“前面”点传入true而“后面”点传入false那么可以获取选定区域开始前后所有的富文本标签都会被选定默认是清除前后所有富文本标签/// /param/// returns/returnspublic int GetRealIndex(TMP_InputField inputField, int surfaceIndex,bool isEndPointfalse) {//string richText inputField.text;//所有surfaceIndex前富文本标签所占的字符总数int allRichTagCharCount 0;total 0;//每次开始前重置total为0//递归获取富文本标签所占的字符总数allRichTagCharCount TryGetRealIndex(richText, surfaceIndex,isEndPoint);//最终实际的定位是富文本字符总数与surfaceIndex表定位的合return allRichTagCharCount surfaceIndex;}/// summary/// 尝试获取真实索引递归方法/// /summary/// param namerichText/param/// param namesurfaceIndex/param/// param nameisEndPoint/param/// returns/returnsprivate int TryGetRealIndex(string richText, int surfaceIndex,bool isEndPoint) {string newString richText;int count 0;//先尝试定位‘’并获取它的定位int mark newString.IndexOf();//-1是没找到没找到或大于原本的定位那么代表原本定位之前已经没有了直接返回结束if ((isEndPoint (mark -1 || mark surfaceIndex)) || //如果是结尾的点那么判断mark时添加等号防止后侧遗留标签整体(!isEndPoint (mark -1 || mark surfaceIndex))) {//如果不是结尾的点那么判断mark时不加等号判断前侧遗留标签整体return total;}//如果在原定位前找到了那么走一遍清除最前的富文本标签并计数的方法else {//清除一次标签并将清除后的字符串保存newString RemoveFrontRichTag(newString, surfaceIndex, ref count);//加入计数total count;//回调继续判断原本定位前是否有富文本标记TryGetRealIndex(newString, surfaceIndex, isEndPoint);}//递归完成后返回最终的富文本标签字符总数return total;}/// summary/// 从前往后移除第一个富文本标签计数标签字符数量并将移除后的字符串返回/// /summary/// param nameaimString待移除富文本标签的目标字符串/param/// param namesurfaceIndex原定位/param/// param namecount用来计数用的 标记已经移除的富文本标签字符长度/param/// returns阶段性返回当前移除的富文本标签字符数量递归后最终返回所有符合要求的富文本标签字符总数量/returnsprivate string RemoveFrontRichTag(string aimString,int surfaceIndex, ref int count) {//先尝试定位int meet aimString.IndexOf();//如果定位不到或者定位超过了原支付长度说明标签在我们所选字符后面或者无富文本标签了方法直接返回并将数量count设置为0if (meet -1 || meet surfaceIndex) {count 0;return aimString;}//成功定位到‘’后继续定位‘’int leave aimString.IndexOf();//将字符串拆分成去掉及其内部内容string newString aimString.Substring(0, meet) aimString.Substring(leave 1, aimString.Length - leave - 1);//计算去掉部分的字符数量int length leave - meet 1;count length;//Debug.Log(newString meet meet leave leave length length);//把去掉已计数的标签后的字符串返回return newString;}#region Utility//移除选定部分所有富文本标签public string RemoveRichTextTags(string text) {return System.Text.RegularExpressions.Regex.Replace(text, .*?, string.Empty);}//移除选定部分所有颜色标签public string RemoveRichTextTags_color(string text) {return System.Text.RegularExpressions.Regex.Replace(text, color.*?|/color, string.Empty);}//移除选定部分所有加粗标签public string RemoveRichTextTags_B(string text) {return System.Text.RegularExpressions.Regex.Replace(text, b|/b, string.Empty);}//移除选定部分所有Size标签public string RemoveRichTextTags_Size(string text) {return System.Text.RegularExpressions.Regex.Replace(text, size.*?|/size, string.Empty);}#endregion
}使用时类似这样
private void Update() {if (Input.GetMouseButtonUp(0)) {OnMouseUpFromIpf();}}#region 主要代码private void OnMouseUpFromIpf() {if (EventSystem.current.currentSelectedGameObject ipf.gameObject) {int startPos ipf.selectionAnchorPosition;//起始选择的位置int endPos ipf.selectionFocusPosition;//结束时的位置if (startPos endPos) return;//如果起始结束相等那么相当于就点了一下没选择内容string selectedStr ;if (startPos endPos) {//正常从前往后选的情况// 获取可见文本的起始位置从选定Index开始排除前面所有富文本标签currentInsideBeginIndex handler.GetRealIndex(ipf, startPos);//获取可见文本的结束位置从选定Index开始后面的所有富文本标签也要排除currentInsideEndIndex handler.GetRealIndex(ipf, endPos, true);//此处传入true即可以排除index后面的所有富文本标签}else if (startPos endPos) {//从后往前选的情况currentInsideBeginIndex handler.GetRealIndex(ipf, endPos);//反选endPos是“前面的点”currentInsideEndIndex handler.GetRealIndex(ipf, startPos, true);//反选startPos是“后面的点”}//获取选定部分的字符串排除选定区域开始前后所有的富文本标签//注意如果需要以选定区域为基准获取区域前后部分的所有富文本标签而不是排除那么需要将BeginIndex的GetRealIndex中IsEndPoint传入true而EndIndex的GetRealIndex中IsEndPoint传入false//类似一个加粗区域bA/b目前选定A那么获取到的是“A”若是以下面的写法反向设置IsEndPoint那么获取到的是“bA/b”。后面这么获取可以方便对标签进行判断和修改selectedStr ipf.text.Substring(currentInsideBeginIndex, currentInsideEndIndex - currentInsideBeginIndex);Debug.Log(currentInsideBeginIndex currentInsideEndIndex selectedStr startPos endPos);ipf_console.text selectedStr;}
} 演示 其他扩展功能只需要对字符串进行编辑即可