在项目中遇到项目要求在描述中进行两端对齐,而我们的 TextView 是不支持两端对齐的
要做到两端对齐,其实还是有些小 trick 的

如上图所示,我们可以在每个字符之间插入一个空格字符,然后动态地计算为了达到某个宽度(即最大宽度),每个空格字符需要多大的宽度,然后使用 ScaleXSpan 将空格字符横向放大/缩小,这样就解决了我们两端对齐的方法,只需要使用一个 TextView 就够了。

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
/**
* 将文字转为两端对齐
* @param maxSize 最大的文字数量
* @param text 文字
* @param textSize 文字大小,单位为 sp 或者 dp
* 举例,假设需要将『三个字』进行两端对齐,最大长度为4个中文字
* 则在『三个字』的每个字符之间插入一个全角空格,并计算其应该放大/缩小的倍数,然后用 ScaleXSpan 对 x 轴方向进行放大/缩放
* @return
*/
public static Spannable formatText(int maxSize,String text,int textSize){
if (TextUtils.isEmpty(text)){
return new SpannableString("");
}
//先获取 maxSize 个字符串的长度
int textLength = text.length();
if (maxSize < textLength || textLength == 1){
return new SpannableString(text);
}
//计算单个中文字在该设备上的长度,单位是 px
float oneCharLength = DisplayMetricsUtil.getTextWidth("正",textSize);
float maxTextLength = oneCharLength * maxSize;
//计算该文字和应有长度的差
float diffLength = maxTextLength - DisplayMetricsUtil.getTextWidth(text,textSize);
//计算每个间隙的宽度
float singleGapLength = diffLength / (textLength -1);
//计算每个间隙应该放大/缩小的倍数
float scale = singleGapLength / oneCharLength;
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
char[] chars = text.toCharArray();
for (int i = 0; i < textLength; i++) {
spannableStringBuilder.append(chars[i]);
if (i != textLength -1){
SpannableString space = new SpannableString(" ");//全角空格
space.setSpan(new ScaleXSpan(scale), 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableStringBuilder.append(space);
}
}
return spannableStringBuilder;
}

计算文字的宽度可以使用 Paint 中的 measureText() 方法

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 根据字体大小获取字符串长度
* @param text 例如 正正正
* @param textSize 18 (单位是 sp 或 dp)
* @return
*/
public static float getTextWidth(String text, int textSize) {
TextPaint paint = new TextPaint();
float scaledDensity = App.getContext().getResources().getDisplayMetrics().scaledDensity;
paint.setTextSize(scaledDensity * textSize);
return paint.measureText(text);
}

使用时只需要调用 formatText 方法对文字进行处理即可

1
textView.setText(formatText(4,"三个字",14));

最后做出来的效果大概如下