自己实现Text控件 - 加入对齐
最终效果,左侧为ugui的,右侧为自己实现的
using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class MyText : Graphic { public Font m_Font; public string m_Text = ""; public int m_FontSize = 40; public TextAnchor m_Alignment; protected MyText() { useLegacyMeshGeneration = false; } //这个必须要提供, OnPopulateMesh中的顶点的uv对应的是这个贴图上的 public override Texture mainTexture { get { if (m_Font != null && m_Font.material != null && m_Font.material.mainTexture != null) return m_Font.material.mainTexture; return base.mainTexture; //默认的白色图片 } } readonly UIVertex[] m_TempVerts = new UIVertex[4]; protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); if (null == m_Font) return; var scale = (m_FontSize / m_Font.fontSize); var lineHeight = scale * m_Font.lineHeight; var ascent = scale * m_Font.ascent; Debug.Log($"scale:{scale}, lineHeight:{lineHeight}, ascent:{ascent}"); var size = rectTransform.rect.size; var pivot = rectTransform.pivot; m_Font.RequestCharactersInTexture(m_Text, m_FontSize); var startPos = new Vector3(-pivot.x * size.x, (1 - pivot.y) * size.y - ascent, 0); var curY = startPos.y; m_Font.RequestCharactersInTexture(m_Text, m_FontSize); float lineWidth = 0; float totalLineHeight = 0; var charInfoLine = new List<CharacterInfo>(); for (int i = 0; i < m_Text.Length; i++) { // Get character rendering information from the font m_Font.GetCharacterInfo(m_Text[i], out var ch, m_FontSize); //Debug.Log($"{m_Text[i]}, {ch.index}, min:({ch.minX}, {ch.minY}), max:({ch.maxX}, {ch.maxY}), {ch.glyphWidth}x{ch.glyphHeight}"); if (lineWidth + ch.advance > size.x) //换行 { DrawLine(vh, startPos.x, curY, ref charInfoLine, lineWidth); lineWidth = 0; curY -= lineHeight; totalLineHeight += lineHeight; } charInfoLine.Add(ch); lineWidth += ch.advance; } if (charInfoLine.Count > 0) { DrawLine(vh, startPos.x, curY, ref charInfoLine, lineWidth); lineWidth = 0; curY -= lineHeight; totalLineHeight += lineHeight; } float vAligh = ((int)m_Alignment / 3) * 0.5f; var yAlighAdjust = (totalLineHeight - size.y) * vAligh; Debug.Log($"vAlign:{vAligh}, yAlighAdjust:{yAlighAdjust}, total:{totalLineHeight}"); for (var i = 0; i < vh.currentVertCount; ++i) { vh.PopulateUIVertex(ref m_TempVerts[0], i); m_TempVerts[0].position.y += yAlighAdjust; vh.SetUIVertex(m_TempVerts[0], i); } } private void DrawLine(VertexHelper vh, float startX, float curY, ref List<CharacterInfo> charInfoLine, float lineWidth) { float hAligh = ((int)m_Alignment % 3) * 0.5f; var size = rectTransform.rect.size; var pos = new Vector3(startX + (size.x - lineWidth) * hAligh, curY, 0); for (var i = 0; i < charInfoLine.Count; ++i) { var ch = charInfoLine[i]; m_TempVerts[0].position = pos + new Vector3(ch.minX, ch.maxY, 0); //左上角 m_TempVerts[0].color = color; m_TempVerts[0].uv0 = ch.uvTopLeft; m_TempVerts[1].position = pos + new Vector3(ch.maxX, ch.maxY, 0); m_TempVerts[1].color = color; m_TempVerts[1].uv0 = ch.uvTopRight; m_TempVerts[2].position = pos + new Vector3(ch.maxX, ch.minY, 0); m_TempVerts[2].color = color; m_TempVerts[2].uv0 = ch.uvBottomRight; m_TempVerts[3].position = pos + new Vector3(ch.minX, ch.minY, 0); m_TempVerts[3].color = color; m_TempVerts[3].uv0 = ch.uvBottomLeft; //0,1,2; 0,2,3 vh.AddUIVertexQuad(m_TempVerts); pos.x += ch.advance; // Advance character position } charInfoLine.Clear(); } }