如何在Runtime通过脚本向TextMeshPro输入框指定位置插入富文本?
平台信息
- 操作系统:Win10
- Unity版本:2022.2.19f1
- TextMeshPro版本:2023.1
- 开发语言:C#
- 构建目标:PC
前置说明
发布此问题前,我已查阅相关推荐帖子,但始终找不到解决方案。现有资料仅涉及替换整个文本内容,或在编辑器中作为开发者添加样式等操作,而非构建后终端用户在Runtime的操作。
我想要制作一个类似论坛发帖编辑器的WYSIWYG(所见即所得)文本编辑器,需要在Runtime将富文本标签(如<b>或</b>)插入到文本内容的指定索引位置,并让TextMeshPro解析这些标签。
我查阅了C#和TMP文档,但无法通过Insert()或其他方法实现字符串插入,搜索结果均为已读过的内容,需要新的研究方向或可运行的简化实现示例,若能提供精简的可运行模型将非常感谢!
问题
如何通过脚本在构建后的Runtime环境下,将字符串或富文本标签插入到指定索引位置?尽可能不替换整个文本内容。
补充说明
我知晓可访问TMP_InputField.Text组件,但无法实现指定索引插入。以下是问题简化代码:画布上有一个TMP_InputField,MonoBehaviour脚本包含该TMP对象的序列化字段,以及一个调试用公共方法,尝试在inputfield.text的索引0处插入“BB”,通过同一画布上的按钮调用此函数。
[SerializeField] private TMP_InputField someTMPObject; public void ButtonFunc_Insert() { // 指定索引插入文本——无效: someTMPObject.text.Insert(0, "start of text array "); // 替换文本——有效: someTMPObject.text = "Replace all text."; // 追加文本——有效: someTMPObject.text += "Add more text to the end!"; }
解决方案
问题核心是C#字符串的不可变性:string.Insert()不会修改原字符串,而是返回一个插入后的新字符串。你之前的代码没有把这个新字符串赋值回someTMPObject.text,所以看起来没有效果。
基础指定索引插入
只需要把Insert()的返回值赋值回InputField,同时可以保留光标位置:
public void ButtonFunc_Insert() { // 获取当前文本 string currentText = someTMPObject.text; // 插入内容(这里以索引0为例,也可以换成光标位置或其他指定索引) string newText = currentText.Insert(0, "<b>开头加粗内容</b>"); // 赋值回InputField someTMPObject.text = newText; // 可选:将光标移到插入内容的末尾 someTMPObject.caretPosition = "<b>开头加粗内容</b>".Length; }
进阶:选中文本包裹富标签(WYSIWYG编辑)
如果要实现类似论坛编辑器的选中加粗/斜体功能,可以结合TMP_InputField的选中区域处理:
public void ToggleBold() { string currentText = someTMPObject.text; int selectStart = someTMPObject.selectionStringAnchorPosition; int selectEnd = someTMPObject.selectionStringFocusPosition; if (selectStart != selectEnd) { // 给选中文本包裹<b>标签 string selectedText = currentText.Substring(selectStart, selectEnd - selectStart); string wrappedText = $"<b>{selectedText}</b>"; string newText = currentText.Remove(selectStart, selectEnd - selectStart).Insert(selectStart, wrappedText); someTMPObject.text = newText; // 光标移到包裹内容末尾 someTMPObject.caretPosition = selectStart + wrappedText.Length; someTMPObject.selectionStringAnchorPosition = someTMPObject.caretPosition; someTMPObject.selectionStringFocusPosition = someTMPObject.caretPosition; } else { // 无选中时,插入<b></b>标签对,光标自动定位到标签之间 string tagPair = "<b></b>"; string newText = currentText.Insert(selectStart, tagPair); someTMPObject.text = newText; someTMPObject.caretPosition = selectStart + "<b>".Length; } }
以上代码均在Runtime环境有效,不需要替换整个文本内容,完全符合所见即所得编辑器的需求。
内容的提问来源于stack exchange,提问作者Valthalin

