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;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/286724.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch8 - Docker安装Elasticsearch8.12.2

前言 最近在学习 ES&#xff0c;所以需要在服务器上装一个单节点的 ES 服务器环境&#xff1a;centos 7.9 安装 下载镜像 目前最新版本是 8.12.2 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.12.2创建配置 新增配置文件 elasticsearch.yml http.host…

费曼学习法:快速掌握新知识!

首先&#xff0c;讲一个关于学习法则的小故事。 马克思普朗克在1918年荣获诺贝尔物理学奖之后&#xff0c;他就在全德国作巡回报告。 不管被邀请到哪里&#xff0c;他就会对新的量子力学演讲一番。 因此&#xff0c;慢慢他的司机也对他的报告烂熟于心&#xff0c;于是就告诉他。…

Java中 List 集合,通过 Stream 流进行排序总结

一、数据准备 public class OrderTest {private String channelCode;private BigDecimal rate;// 省略 getter、setter、toString()、constructor }List<OrderTest> orderTestList new ArrayList<>();OrderTest z09 new OrderTest("Z09", new BigDeci…

是德科技KEYSIGHT E4990A阻抗分析仪

181/2461/8938产品概述: E4990A 阻抗分析仪具有 20 Hz 至 120 MHz 的频率范围&#xff0c;可在宽阻抗范围内提供出色的 0.045%&#xff08;典型值&#xff09;基本准确度&#xff0c;并内置 40 V 直流偏置源&#xff0c;适用于元器件、半导体和材料测量。 无论研发、生产、质…

SpringMvc执行流程源码解析

一、简介 Spring web Mvc是基于ServletApi构建的原始Web模块&#xff0c;从一开始就包含在Spring框架中&#xff1b; 从Servlet到SpringMvc 最典型的MVc就是JSPServletjavaBean的模式&#xff1b; 弊端&#xff1a; 1、xml下配置Servlet的映射非常麻烦&#xff0c;效率低&…

【 yolo红外微小无人机-直升机-飞机-飞鸟目标检测】

yolo无人机-直升机-飞机-飞鸟目标检测 1. 小型旋翼无人机目标检测2. yolo红外微小无人机-直升机-飞机-飞鸟目标检测3. yolo细分类型飞机-鸟类-无人机检测4. yolo红外大尺度无人机检测5. 小型固定翼无人机检测6. 大型固定翼无人机检测7. yolo航空俯视场景下机场飞机检测 1. 小型…

git clone拉取项目时报错xxx bytes of body are still expected

报错如下&#xff1a; 尝试了网友们的各种方法&#xff1a; 1、可能缓存区溢出&#xff0c;执行以下语句&#xff0c;将缓存设置为500M或者更大 git config http.postBuffer 524288000 2、可能项目过大&#xff0c;先进行浅克隆&#xff0c;然后更新远程库到本地 git clone…

鸿蒙APP应用开发教程—超详细的项目结构说明

1. 新建项目 打开DevEco Studio, 选择 Create Project: 1.1 选择模版 Create Project - Choose Template 1.2 配置项目 Create Project - Configure Project 如果使用的是 DevEco 3.X 版本, 可以根据 Compile SDK版本选择不同的模式, 比如: 3.0.0(API 8)及更早 - 仅支持 …

Python学习:循环语句

Python循环语句 概念 循环语句是编程中常用的结构&#xff0c;用于多次执行相同或类似的代码块。Python中有两种主要的循环语句&#xff1a;for循环和while循环。 for循环&#xff1a; for循环用于遍历一个序列&#xff08;如列表、元组、字符串等&#xff09;中的元素&#x…

VUE之首次加载项目缓慢

最近公司有个大型的项目&#xff0c;使用vue2开发的&#xff0c;但是最终开发完成之后&#xff0c;项目发布到线上&#xff0c;首次加载项目特别缓慢&#xff0c;有时候至少三十秒才能加载完成&#xff0c;加载太慢了&#xff0c;太影响用户体验了&#xff0c;最近研究了一下优…

“一树生三花”战略背后,梦之蓝·手工班的新使命

执笔 | 尼 奥 编辑 | 扬 灵 绵柔酒香&#xff0c;洋河酒韵。3月17日&#xff0c;由洋河股份主办的中国白酒发展趋势高峰论坛暨梦之蓝手工班战略升级发布会在成都隆重举办&#xff0c;协会领导、行业专家、名商大商齐聚一堂&#xff0c;梦之蓝手工班三款产品首次集体亮相&…

【第十二届“泰迪杯”数据挖掘挑战赛】【2024泰迪杯】B题基于多模态特征融合的图像文本检索—解题全流程(持续更新)

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛B题 解题全流程&#xff08;持续更新&#xff09; -----基于多模态特征融合的图像文本检索 一、写在前面&#xff1a; ​ 本题的全部资料打包为“全家桶”&#xff0c; “全家桶”包含&#xff1a;模型数据、全套代码、训练好的模…

NVIDIA NIM 提供优化的推理微服务以大规模部署 AI 模型

NVIDIA NIM 提供优化的推理微服务以大规模部署 AI 模型 生成式人工智能的采用率显着上升。 在 2022 年 OpenAI ChatGPT 推出的推动下&#xff0c;这项新技术在几个月内就积累了超过 1 亿用户&#xff0c;并推动了几乎所有行业的开发活动激增。 到 2023 年&#xff0c;开发人员…

QT 界面2.1

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {this->setWindowIcon(QIcon(":/Logo/1bc87d9b4c1ea878d5e0845257a06f7f (1).jpg")); // 图标this->setWindowTitle(&…

mysql日志管理 、备份与恢复

目录 一 MySQL 日志 &#xff08;一&#xff09;&#xff0c;日志位置 &#xff08;二&#xff09;配置文件中 与日志相关的代码 1&#xff0c;错误日志 2&#xff0c;通用查询日志 3&#xff0c;二进制日志(binlog) 4&#xff0c;中继日志 5&#xff0c;慢查询日志…

「薪酬设计」某维修服务公司维修技术人员薪酬体系设计项目纪实

——搭建合理薪酬制度&#xff0c;有效激励维修技术人员 本次薪酬体系设计项目持续的时间比较长&#xff0c;前后大约持续了半年时间&#xff0c;华恒智信团队对公司的多个模块都给予了分析&#xff0c;提供了建议方案&#xff0c;专家比较细心&#xff0c;服务很全面&#xf…

测试的思路总结

背景 这两天有一个之前做的需求出了问题。业务整体是一个流程类的业务&#xff0c;先通过一个多阶段的弹窗页面&#xff0c;从ABCDE等多个条件中选取三个生成一个任务&#xff0c;然后后台去跑任务&#xff0c;生成数据。具体需求是根据弹窗中的条件中&#xff0c;修改A、B、C…

C语言例4-14:从键盘输入小写字母转换成大写字母并输出。

代码如下&#xff1a; //从键盘输入小写字母转换成大写字母并输出。 #include<stdio.h> int main(void) {char c1,c2;printf("输入小写字母&#xff1a; \n");c1 getchar(); //从键盘输入一个字符putchar(c1);printf(",%d\n",c1);c2 c1-32; …

AI研报:从Sora看多模态大模型发展

《从Sora看多模态大模型发展》的研报来自浙商证券&#xff0c;写于2024年2月。 这篇报告主要探讨了多模态大模型的发展趋势&#xff0c;特别是OpenAI发布的视频生成模型Sora&#xff0c;以及其对行业发展的影响。以下是报告的核心内容概述&#xff1a; Sora模型的发布&#x…

unity小:使用Unity FBX Exporter 将 3DMax场景或者模型无损导入Unity

本指南旨在帮助您顺利安装和配置Unity FBX Exporter插件&#xff0c;并解决相关的常见问题。 安装 FBX Exporter 下载并安装FBX Exporter插件。 打开Unity&#xff0c;选择 Edit > Project Settings > Fbx Export。 点击 Install Unity Integration 并选择3ds Max的插…