今天遇到了一个需求,需要将文本竖排排列,查到了一个网上的方案
但是这个方案有几个问题(BUG)

  • 文本的位置会跟着锚点变化
  • 每行的最后几个字的布局是错的

因为他是基于横版的文本排版结果,所以文本框的宽度也会影响他的换行,而且会造成文本框的大小范围和文本的不一致
于是我在他原来的思路上把它继续改进了下,并且增加了注释便于理解
思路就是重新实现一套排版机制,对换行符特殊处理,然后继续沿用原来修改顶点位置的方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using UnityEngine;  
using UnityEngine.UI;

[AddComponentMenu(""UI/TextVerticalCompoent"", 10)]
public class TextVerticalCompoent : Text
{
public bool m_Virtical = true;
private float lineSpace = 1;
private float textSpace = 1;
private float xOffset = 0;
private float yOffset = 0;

#if UNITY_EDITOR
protected override void OnValidate()
{
base.OnValidate();

//关闭自动裁切文本
//解决有时裁切文本会出错的问题
verticalOverflow = VerticalWrapMode.Overflow;
}
#endif

protected override void OnPopulateMesh(VertexHelper toFill)
{
base.OnPopulateMesh(toFill);
if (m_Virtical)
{
VirticalText(toFill);
}
}

private void VirticalText(VertexHelper toFill)
{
if (!IsActive())
return;

lineSpace = fontSize * lineSpacing;
textSpace = fontSize ;

//排除掉锚点变化造成的影响
xOffset = rectTransform.rect.width + rectTransform.rect.x - fontSize / 2;
yOffset = rectTransform.rect.height + rectTransform.rect.y - fontSize / 2;

//重新计算一版排版
int row = 0;
int col = 0;
float height = fontSize / 2;

int minCount = toFill.currentVertCount / 4;

if (rectTransform.rect.height < fontSize)
{
return;
}

for (int i = 0; i < minCount; i++)
{
if (height > rectTransform.rect.height || text[i] == '\n')
{
col++;
row = 0;
height = fontSize / 2;
}

ModifyText(toFill, i, row, col);

if (text[i] != '\n')
{
row++;
height += fontSize;
}
}
}

void ModifyText(VertexHelper helper, int i, int charYPos, int charXPos)
{
//Text 的绘制是每4个顶点绘制一个字符
//按字符顺序取出顶点,则可以获得字符的位置
//并对其进行修改

//取出原来顶点的位置
UIVertex lb = new UIVertex();
helper.PopulateUIVertex(ref lb, i * 4);

UIVertex lt = new UIVertex();
helper.PopulateUIVertex(ref lt, i * 4 + 1);

UIVertex rt = new UIVertex();
helper.PopulateUIVertex(ref rt, i * 4 + 2);

UIVertex rb = new UIVertex();
helper.PopulateUIVertex(ref rb, i * 4 + 3);

//计算文本的中心点
Vector3 center = Vector3.Lerp(lb.position, rt.position, 0.5f);

float x = -charXPos * lineSpace + xOffset;
float y = -charYPos * textSpace + yOffset;

//计算字符新位置
Vector3 pos = new Vector3(x, y, 0);

lb.position = lb.position - center + new Vector3(x, y, 0);
lt.position = lt.position - center + new Vector3(x, y, 0);
rt.position = rt.position - center + new Vector3(x, y, 0);
rb.position = rb.position - center + new Vector3(x, y, 0);

helper.SetUIVertex(lb, i * 4);
helper.SetUIVertex(lt, i * 4 + 1);
helper.SetUIVertex(rt, i * 4 + 2);
helper.SetUIVertex(rb, i * 4 + 3);
}
}

图片

也可以点击这里下载这个类

原文地址:一个更好的UGUI 竖排文本方案