TextMeshPro图文混排的两种实现方式,不打图集

2024-03-23 00:04

本文主要是介绍TextMeshPro图文混排的两种实现方式,不打图集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

TMP图文混排

    • 方案一:TMP自带图文混排
      • 使用方法
        • 打包图集
        • 使用
    • 方案二:不打图集,可以使用任何图片

接到一个需求,TextMeshPro 图文混排。

方案一:TMP自带图文混排

优点布局适应优秀,字体左中右布局位置都很不错
缺点用到的图片需要打包,使用Resources加载

使用方法

打包图集

打包图集这里推荐使用TexturePacker工具,功能强大,完美适配。这个软件也可以用于压缩图集。

TexturePacker链接

1.将你需要的散图或文件夹拖到这个区域,或使用添加精灵按钮添加。

2.选中下图按钮,选择Json(Array), 注意是Array。
下面的图片模式和打包可以自己尝试,主要是控制压缩和图片格式,这里不做介绍。

3.点击发布,获得一个Json文件和一张PNG,Json 是PNG各个图片的位置信息。

4.将上一步的资源导入Unity,然后打开TextMeshPro的图集工具 Sprite Importer。

5.将Json 和PNG 拖入下图中对应的位置。点击生成,然后存储到自己的文件夹

使用

1.将生成的图集拖入TMP的Sprite Asset中,使用图片时,在字符串中插入<sprite=你的图片id>,例如图中“<sprite=0> 图片好看吗”

2. ??? 图片咋这样??? ,发现图片大小不对,被勾选了自动转变为2的n次方。这里改成None ,图片能完整显示了

3. 还是不对,位置偏差好多,按下图2修改X和Y的偏移,最下方的Global Offset 是同时修改所有图片

完成啦,撒花~~

方案二:不打图集,可以使用任何图片

优点当你有大量图片都可能用于图文混排,不方便打包时使用。代码没多少,随便修随便改- -
缺点对布局适配一般,只支持了整个组件的对齐,文字只支持了左对齐

原理就是将含图片的文本拆分成几段文本和图片的组合,计算位置,使用多个TMP和图片拼接
图片暂定格式 [img] 图片ID[/img]

using System.Collections.Generic;
using System.Text.RegularExpressions;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class TextImageView : MonoBehaviour
{public enum TextImageAlignmentH{Left,Center,Right}public enum TextImageAlignmentV{Top,Center,Bottom}public Transform content;public int FontSize;public float maxWidth;public TextMeshProUGUI tmp;public Image img;public TextImageAlignmentH alignmentH = TextImageAlignmentH.Center;public TextImageAlignmentV alignmentV = TextImageAlignmentV.Center;private float _lineHeight;private float _averageWidth;private float _maxLength;private List<KeyValuePair<string, int>> _contentList = new List<KeyValuePair<string, int>>();public string text{set { Test(value); }}public void Test(string text){_contentList = StringToKeyValuePair(text);var reduceWidth = 0f;var height = 0f;tmp.fontSize = FontSize;tmp.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, maxWidth);tmp.gameObject.SetActive(true);tmp.text = "test";tmp.ForceMeshUpdate();_lineHeight = tmp.textInfo.lineInfo[0].lineHeight;tmp.gameObject.SetActive(false);content.DestroyChildren();for (var i = 0; i < _contentList.Count; i++){if (_contentList[i].Value == 0){var label = TestText(_contentList[i].Key, reduceWidth,height);for (var i1 = 0; i1 < label.textInfo.lineInfo.Length; i1++){var lineInfo = label.textInfo.lineInfo[i1];var width = lineInfo.length;if(_maxLength < width){_maxLength = width;}if(i1 == label.textInfo.lineCount - 1){height = (label.transform.localPosition.y - i1*_lineHeight);reduceWidth = maxWidth - width - 5;}}}else{var imgData = TestImage(_contentList[i].Key, reduceWidth, height);reduceWidth = imgData.reduce + 5;if (_maxLength < (maxWidth - imgData.reduce)){_maxLength = maxWidth - imgData.reduce;}if(imgData.changeLine){height -= _lineHeight;}}}height -= _lineHeight;var x = 0f;switch (alignmentH){case TextImageAlignmentH.Left:x = 0;break;case TextImageAlignmentH.Center:x = (maxWidth - _maxLength) / 2;break;case TextImageAlignmentH.Right:x = maxWidth - _maxLength;break;}var y = 0f;switch (alignmentV){case TextImageAlignmentV.Top:y = _lineHeight;break;case TextImageAlignmentV.Center:y = -height/2 +_lineHeight/2;break;case TextImageAlignmentV.Bottom:y = -height;break;}content.transform.localPosition = new Vector3(x,y,0);}// <color=#FFFFFF><sprite=1/> 计分时\n<color=#FF0000>+4 </color>倍率</color>private List<KeyValuePair<string, int>> StringToKeyValuePair(string text){var result = new List<KeyValuePair<string, int>>();// 拆分字符串,匹配图片名和文字内容var splitText = Regex.Split(text, @"(\[img\]|\[/img\])");// 遍历拆分后的字符串for (var i = 0; i < splitText.Length; i++){switch (splitText[i]){case "[img]":{// 如果是图片名,将它加入结果列表result.Add(new KeyValuePair<string, int>(splitText[i + 1], 1));// 跳过处理下一个字符串i++;}continue;case "[/img]":// 如果是 [/img] ,跳过处理下一个字符串continue;default:{var content = splitText[i];if (string.IsNullOrEmpty(content)){continue;}result.Add(new KeyValuePair<string, int>(content, 0));}break;}}return result;}public string testValue;[ContextMenu("测试")]public void Test1(){// TestText(testValue, 300,0);Test(testValue);}private TextMeshProUGUI TestText(string value,float reduceWidth,float height){var obj = GameObject.Instantiate((UnityEngine.Object)tmp.gameObject) as GameObject;//GameObject obj = null;if (obj == null){return null;}obj.SetActive(true);if(_averageWidth == 0){_averageWidth = obj.GetComponent<TextMeshProUGUI>().GetPreferredValues(value).x/ value.Length;}var label = obj.GetComponent<TextMeshProUGUI>();label.fontSize = FontSize;label.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, maxWidth); obj.transform.SetParent(content);obj.transform.localScale = Vector3.one;if (reduceWidth <= _averageWidth)//剩下的空间不够一个字,直接换行{obj.transform.localPosition = new Vector3(0, height - _lineHeight, 0);}else{value = $"<space={maxWidth - reduceWidth}>{value}"; // 创建新字符串obj.transform.localPosition = new Vector3(0, height, 0); }value = DelUrlFlag(value);label.text = value;label.ForceMeshUpdate();return label; // 计算剩余宽度}private (bool changeLine,float reduce) TestImage(string value,float reduceWidth,float height){var obj = GameObject.Instantiate((UnityEngine.Object)img.gameObject) as GameObject;if (obj == null){return (false,reduceWidth);}obj.SetActive(true);var sp = obj.GetComponent<Image>();sp.SetIcon(int.Parse(value));//value是图片的ID,这里替换为自己的设置图片的方法var tempHeight = _lineHeight ;sp.SetNativeSize();var size = sp.rectTransform.sizeDelta;var rate = size.y / tempHeight;sp.rectTransform.sizeDelta = new Vector2(size.x / rate, tempHeight);var needWidth = sp.rectTransform.sizeDelta.x;obj.transform.SetParent(content);obj.transform.localScale = Vector3.one;if (needWidth > reduceWidth){obj.transform.localPosition = new Vector3(-maxWidth/2 +needWidth/2, height - _lineHeight, 0);return (true,maxWidth -needWidth);}else{obj.transform.localPosition = new Vector3(-maxWidth/2 + (maxWidth - reduceWidth)+needWidth/2, height, 0);return (false,reduceWidth - needWidth);}}private string DelUrlFlag(string strTxt){strTxt = strTxt.Replace("[/url]", "");int nStartLeftBracket = 0;int nStartRightBracket = 0;while (true){nStartLeftBracket = strTxt.IndexOf('[', nStartLeftBracket);nStartRightBracket = strTxt.IndexOf(']', nStartRightBracket);if (nStartLeftBracket > -1 && nStartRightBracket > -1 && nStartRightBracket > nStartLeftBracket){string sub = strTxt.Substring(nStartLeftBracket, nStartRightBracket - nStartLeftBracket + 1);if (sub.Contains("url")){strTxt = strTxt.Remove(nStartLeftBracket, nStartRightBracket - nStartLeftBracket + 1);nStartLeftBracket = 0;nStartRightBracket = 0;}else{nStartLeftBracket = nStartRightBracket;nStartRightBracket += 1;}}else{break;}}return strTxt;}
}

这篇关于TextMeshPro图文混排的两种实现方式,不打图集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/836524

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.