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

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

大家好,欢迎来到IT知识分享网。

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

方案一:TMP自带图文混排

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

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

使用方法

打包图集

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

TexturePacker链接

1.将你需要的散图或文件夹拖到这个区域,或使用添加精灵按钮添加。
TextMeshPro图文混排的两种实现方式,不打图集

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

3.点击发布,获得一个Json文件和一张PNG,Json 是PNG各个图片的位置信息。
TextMeshPro图文混排的两种实现方式,不打图集

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

4.将上一步的资源导入Unity,然后打开TextMeshPro的图集工具 Sprite Importer。
TextMeshPro图文混排的两种实现方式,不打图集

5.将Json 和PNG 拖入下图中对应的位置。点击生成,然后存储到自己的文件夹
TextMeshPro图文混排的两种实现方式,不打图集

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

使用

1.将生成的图集拖入TMP的Sprite Asset中,使用图片时,在字符串中插入<sprite=你的图片id>,例如图中“<sprite=0> 图片好看吗”
TextMeshPro图文混排的两种实现方式,不打图集

2. ??? 图片咋这样??? ,发现图片大小不对,被勾选了自动转变为2的n次方。这里改成None ,图片能完整显示了
TextMeshPro图文混排的两种实现方式,不打图集

3. 还是不对,位置偏差好多,按下图2修改X和Y的偏移,最下方的Global Offset 是同时修改所有图片
TextMeshPro图文混排的两种实现方式,不打图集

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

完成啦,撒花~~

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

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

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

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

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132462.html

(0)
上一篇 2025-07-31 14:45
下一篇 2025-07-31 15:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信