发现问题
新版本引入了一个新勋章,测试走查其多语言时发现,泰文版勋章名没有一行展示而是换行了,如图所示:
因为其他语言没问题、泰文版其他勋章名也是正常的,所以第一反应是有问题的泰文是不是误加了换行符?经查并没有。而且在限制勋章名Text组件最多展示一行且按照末尾打点后,原本换到第二行的内容也被打点掉了:
这时尝试给Text一个最大宽度,没有任何变化:
return ConstrainedBox(
constraints: BoxConstraints(maxWidth: 150),
child: Text(...),
)
接着尝试给Text一个固定宽度,此时终于能正常一行展示了:
return Container(
width: 150,
child: Text(...),
);
但这不符合设计,Text后面紧挨着一个小问号,要求Text是自适应宽度的,因此要给Text一个实际宽度才行,但仅算出来的宽度还不行,要多加一点宽度才可以:
final painter = TextPainter(
textDirection: TextDirection.ltr,
maxLines: 1,
text: TextSpan(
text: ...,
style: ...,
),
);
painter.layout(minWidth: 0, maxWidth: 150);
return Container(
width: painter.width + 2, // 2就是额外宽度
child: Text(...),
);
最终效果如图:
定位原因
本以为这个问题算是解决了,在自测时突然发现好几处都有类似问题,比如这个页面圈出来的几处泰文,如果限制了最大行数会表现为提前打点、未限制时会表现为莫名换行,且只有泰文有问题:
这些泰文的相同点是最后一个字符都包含
-์
,为验证的确是该符号引起,做了如下测试:那是否只有
-์
符号会导致错误呢?wiki-泰文字一文了解在泰文共包含这些字母:其中,红框圈出的被称为组合符号(Combining Character),即可以加在前一个字母之上:
经过测试,这16个组合符号中有4个会导致显示异常(前四个):
其实也不难猜到,因为这4个符号明显超出底部辅音字母宽度,且超出部分能在后一个辅音字母的空间中显示。因此,如果它们不在最后一个,实际宽度就等于测量宽度(辅音字母宽度之和);如果处于最后一个,实际宽度就大于测量宽度,导致换行或打点。
解决办法
这里提供几种解决思路:
1、直接修改翻译,或在文本后加一个空格即可,可以快速修复线上问题
2、优化Text组件,兼容泰文这几个特殊符号处于最后一个的情况
3、设置字体,如Google提供的这一款泰文字体 Google Fonts-Noto Serif Thai 可以调整组合字符的显示区域,使之不超出辅音字母。
总结
突然发现最近三篇BUG系列都是多语言问题,在解决问题过程中也学习各个地区语言的与众不同,也是很有意思的经历了~