网站项目ppt怎么做/企业网站建设规划
一、带富文本标签的框选是什么
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
进而扩展一下,今天<b><i><color=yellow>没有</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 name="aimString">待移除富文本标签的目标字符串</param>
/// <param name="surfaceIndex">原定位</param>
/// <param name="count">用来计数用的, 标记已经移除的富文本标签字符长度</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 name="richText"></param>
/// <param name="surfaceIndex"></param>
/// <param name="isEndPoint"></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 name="inputField"></param>
/// <param name="surfaceIndex"></param>
/// <param name="isEndPoint">
/// 默认为false,从选定位置往前,所有富文本标签<>全部排除(通常为选定部分的“前面”点)
/// 传入true后,从选定位置开始,不仅往前,而且往后,所有富文本标签<>全部排除(通常为选定部分“后面”点)
/// 注意:选定时,从前往后选和从后往前选,“前面”和“后面”的点要判断一下
/// 扩展:如果“前面”点传入true,而“后面”点传入false,那么可以获取选定区域开始,前后所有的富文本标签都会被选定(默认是清除前后所有富文本标签)
/// </param>
/// <returns></returns>
public int GetRealIndex(TMP_InputField inputField, int surfaceIndex,bool isEndPoint=false) {//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 name="inputField"></param>/// <param name="surfaceIndex"></param>/// <param name="isEndPoint">/// 默认为false,从选定位置往前,所有富文本标签<>全部排除(通常为选定部分的“前面”点)/// 传入true后,从选定位置开始,不仅往前,而且往后,所有富文本标签<>全部排除(通常为选定部分“后面”点)/// 注意:选定时,从前往后选和从后往前选,“前面”和“后面”的点要判断一下/// 扩展:如果“前面”点传入true,而“后面”点传入false,那么可以获取选定区域开始,前后所有的富文本标签都会被选定(默认是清除前后所有富文本标签)/// </param>/// <returns></returns>public int GetRealIndex(TMP_InputField inputField, int surfaceIndex,bool isEndPoint=false) {//string richText = inputField.text;//所有,surfaceIndex前,富文本标签所占的字符总数int allRichTagCharCount = 0;total = 0;//每次开始前,重置total为0//递归获取富文本标签所占的字符总数allRichTagCharCount = TryGetRealIndex(richText, surfaceIndex,isEndPoint);//最终实际的定位是,富文本字符总数与surfaceIndex表定位的合return allRichTagCharCount + surfaceIndex;}/// <summary>/// 尝试获取真实索引,递归方法,/// </summary>/// <param name="richText"></param>/// <param name="surfaceIndex"></param>/// <param name="isEndPoint"></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;}/// <summary>/// 从前往后,移除第一个富文本标签,计数标签字符数量,并将移除后的字符串返回/// </summary>/// <param name="aimString">待移除富文本标签的目标字符串</param>/// <param name="surfaceIndex">原定位</param>/// <param name="count">用来计数用的, 标记已经移除的富文本标签字符长度</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;}#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//类似一个加粗区域,<b>A</b>,目前选定A,那么获取到的是“A”,若是以下面的写法反向设置IsEndPoint,那么获取到的是“<b>A</b>”。后面这么获取,可以方便对标签进行判断和修改selectedStr = ipf.text.Substring(currentInsideBeginIndex, currentInsideEndIndex - currentInsideBeginIndex);Debug.Log(currentInsideBeginIndex + " " + currentInsideEndIndex + " " + selectedStr+" "+startPos+" "+endPos);ipf_console.text = selectedStr;}
}
演示
其他扩展功能,只需要对字符串进行编辑即可
相关文章:

Unity TMP Inputfield 输入框 框选 富文本 获取真实定位
一、带富文本标签的框选是什么 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition,开始选择时的光标下标和当前光标下标 对于未添加富文本标签时,直接通过以上两个值,判断一下框选方向(前向后/后向前&…...

如何在原生项目中集成flutter
两个前提条件: 从flutter v1.17版本开始,flutter module仅支持AndroidX的应用在release模式下flutter仅支持一下架构:x84_64、armeabi-v7a、arm6f4-v8a,不支持mips和x86;所以引入flutter前需要在app/build.gradle下配置flutter支持的架构 a…...

【设计模式】策略模式
目录 什么是策略模式 代码实现 什么是策略模式 策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装成一个独立的对象,使得它们可以相互替换。 在策略模式中,通常有三个角色: 环境类(Cont…...

Java面试八股之Iterator和ListIterator的区别是什么
Iterator和ListIterator的区别是什么 这道题也是考查我们对迭代器相关的接口的了解程度,从代码中我们可以看出后者是前者的子接口,在此基础上做了一些增强,并且只用于List集合类型。 定义与基本概念 Iterator: 定义:…...

服务器中毒怎么办?企业数据安全需重视
互联网企业: 广义的互联网企业是指以计算机网络技术为基础,利用网络平台提供服务并因此获得收入的企业。广义的互联网企业可以分为:基础层互联网企业、服务层互联网企业、终端层互联网企业。 狭义的互联网企业是指在互联网上注册域名,建立网…...

k8s使用harbor私有仓库镜像 —— 筑梦之路
官方文档: Secret | Kubernetes ImagePullSecrets的设置是kubernetes机制的另一亮点,习惯于直接使用Docker Pull来拉取公共镜像,但非所有容器镜像都是公开的。此外,并不是所有的镜像仓库都允许匿名拉取,也就是说需要身份认证&…...

tcp bbr pacing 的对与错
前面提到 pacing 替代 burst 是大势所趋,核心原因就是摩尔定律逐渐失效,主机带宽追平交换带宽,交换机不再能轻易吸收掉主机突发,且随着视频类流量激增,又不能以大 buffer 做带宽后备。因此,主机必须 pacing…...

MySQL学习-非事务相关的六大日志、InnoDB的三大特性以及主从复制架构
一. 六大日志 慢查询日志:记录所有执行时间超过long_query_time的查询,方便定位并优化。 # 查询当前慢查询日志状态 SHOW VARIABLES LIKE slow_query_log; #启用慢查询日志 SET GLOBAL slow_query_log ON; #设置慢查询文件位置 SET GLOBAL slow_query_log_file …...

【软件测试】MIL/HIL/PIL/SIL测试
V字型开发流程 引用文章:汽车行业V模型开发详解 V模型开发(V-Model Development)是一种广泛应用于汽车行业的系统开发方法。它以字母“V”形状的图表形式展示了开发过程中不同阶段之间的关系,从需求分析到系统整合和验证&#x…...

WebKit结构深度解析:打造高效与安全的浏览器引擎
WebKit结构深度解析:打造高效与安全的浏览器引擎 在现代网络世界中,浏览器作为连接用户与互联网信息的桥梁,其背后的技术架构至关重要。WebKit,作为当今最流行的开源浏览器引擎之一,其结构设计和功能实现对于提升浏览…...

SQLSERVER对等发布问题处理
问题1: 无法对 数据库Sast_Business 执行 删除,因为它正用于复制。 (.Net SqlClient Data Provider) 处理: USE [master]; GO EXEC sp_replicationdboption dbname NSast_Business, optname Npublish, value Nfalse; EXEC sp_replica…...

CentOS 7 中时间快了 8 小时
1.查看系统时间 1.1 timeZone显示时区 [adminlocalhost ~]$ timedatectlLocal time: Mon 2024-04-15 18:09:19 PDTUniversal time: Tue 2024-04-16 01:09:19 UTCRTC time: Tue 2024-04-16 01:09:19Time zone: America/Los_Angeles (PDT, -0700)NTP enabled: yes NTP synchro…...

itext7 pdf转图片
https://github.com/thombrink/itext7.pdfimage 新建asp.net core8项目,安装itext7和system.drawing.common 引入itext.pdfimage核心代码 imageListener下有一段不安全的代码 unsafe{for (int y 0; y < image.Height; y){byte* ptrMask (byte*)bitsMask.Scan…...

搜维尔科技:Manus Xsens Metagloves新一代手指捕捉
Manus Xsens Metagloves新一代手指捕捉 搜维尔科技:Manus Xsens Metagloves新一代手指捕捉...

Python与Redis:提升性能,确保可靠性,掌握最佳实践
在 Python 中,有多个库可用于与 Redis 数据库进行交互,其中最受欢迎的是 redis-py。这是一个 Python 客户端库,提供了与 Redis 数据库进行通信的丰富功能。 Python操作Redis操作步骤 安装 redis-py 使用 pip 安装 redis-py: p…...

GPT国内能用吗
2022年11月,Open AI发布ChatGPT,ChatGPT展现了大型语模型在自然语言处理方面的惊人进步,其生成文本的流畅度和连贯性令人印象深刻,为AI应用打开了新的可能性。 ChatGPT的出现推动了AI技术在各个领域的应用,例如&#x…...

中科亿海微-CL1656功能验证开发板
I. 引言 A. 研究背景与意义 CL1656是一款精度高、功耗低、成本低的5V单片低功耗运放,由核心互联公司研发制造,CL1656 是一个 16-bit、快速、低功耗逐次逼近型 ADC,吞吐速率高达 250 kSPS,并且内置低噪声、宽 带宽采样保持放大器。…...

学习STM32第十五天
SPI外设 一、简介 STM32F4XX内部集成硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU负担,可配置8位/16位数据帧,高位(最常用)/低位先行,三组SPI接口,支持DMA…...

【面试题】MySQL 事务的四大特性说一下?
事务是一个或多个 SQL 语句组成的一个执行单元,这些 SQL 语句要么全部执行成功,要么全部不执行,不会出现部分执行的情况。事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 事务的主要作用是保证数…...

案例实践 | InterMat:基于长安链的材料数据发现与共享系统
案例名称:InterMat-基于区块链的材料数据发现与共享系统 ■ 建设单位 北京钢研新材科技有限公司 ■ 用户群体 材料数据上下游单位 ■ 应用成效 已建设10共识节点、50轻节点,1万注册用户 案例背景 材料是构成各种装备和工程的物质载体,…...

【数据挖掘】实验8:分类与预测建模
实验8:分类与预测建模 一:实验目的与要求 1:学习和掌握回归分析、决策树、人工神经网络、KNN算法、朴素贝叶斯分类等机器学习算法在R语言中的应用。 2:了解其他分类与预测算法函数。 3:学习和掌握分类与预测算法的评…...

go语言并发实战——日志收集系统(三) 利用sarama包连接KafKa实现消息的生产与消费
环境的搭建 Kafka以及相关组件的下载 我们要实现今天的内容,不可避免的要进行对开发环境的配置,Kafka环境的配置比较繁琐,需要配置JDK,Scala,ZoopKeeper和Kafka,这里我们不做赘述,如果大家不知道如何配置环境&#x…...

Go 单元测试之Mysql数据库集成测试
文章目录 一、 sqlmock介绍二、安装三、基本用法四、一个小案例五、Gorm 初始化注意点 一、 sqlmock介绍 sqlmock 是一个用于测试数据库交互的 Go 模拟库。它可以模拟 SQL 查询、插入、更新等操作,并且可以验证 SQL 语句的执行情况,非常适合用于单元测试…...

Prometheus + Grafana 搭建监控仪表盘
目标要求 1、需要展现的仪表盘: SpringBoot或JVM仪表盘 Centos物理机服务器(实际为物理分割的虚拟服务器)仪表盘 2、展现要求: 探索Prometheus Grafana搭建起来的展示效果,尽可能展示能展示的部分。 一、下载软件包 监控系统核心…...

机器人管理系统的增删查改(Python)
#交互模式 robot ["机器人1","机器人2","机器人3","机器人4"] name input("请输入您的姓名:") print("%s您好欢迎使用机器人管理系统"%(name))while True:print("您可以进行 1.查找 2.修改 3.增…...

【.Net动态Web API】背景与实现原理
🚀前言 本文是《.Net Core进阶编程课程》教程专栏的导航站(点击链接,跳转到专栏主页,欢迎订阅,持续更新…) 专栏介绍:通过源码实例来讲解Asp.Net Core进阶知识点,让大家完全掌握每一…...

JS-43-Node.js02-安装Node.js和npm
Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,可以让JavaScript实现后端开发,所以,首先在本机安装Node.js环境。 一、安装Node.js 官网:下载 Node.js 默认两个版本的下载: 64位windows系统的LTS(Long Tim…...

设计模式(分类)
目录 设计模式(分类) 设计模式(六大原则) 设计模式是软件工程中一种经过验证的、用于解决特定设计问题的通用解决方案。它们是面向对象编程(Object-Oriented Programming, OOP)实践中提炼出的最佳实…...

请陪伴Kimi和GPT成长
经验的闪光汤圆 但是我想要写实的 你有吗? 岁数大了,希望如何学习新知识呢?又觉得自己哪些能力亟需补强呢? 看论文自然得用Kimi,主要是肝不动了,眼睛也顶不住了。 正好昨天跟专业人士学会了用工作流的办法跟…...

优思学院|ISO45001职业健康安全管理体系是什么?
ISO45001:2018是新公布的国际标准规范,全球备受期待的职业健康与安全国际标准(OH&S)于2018年公布,并将在全球范围内改变工作场所实践。ISO45001将取代OHSAS18001,成为全球工作场所健康与安全的参考。 ISO45001:201…...