前言
~
項目截圖
最近同事在項目中遇到,TextView文字兩端對齊的問題,就如同上圖的效果5個字和4個字的文字首尾對齊。當然上圖的實現方式是承載的H5頁面,并不是原生的TextView。可是這個問題一直困擾著我,想試試用原生的TextView能不能做出這個效果,于是就有了今天這篇文章。
1.初步實現效果
~
原生TextView實現對齊效果
效果還不錯吧,使用起來也是非常的簡單:
tv1.setText(AlignedTextUtils.formatText("手 機 號"));
tv2.setText(AlignedTextUtils.formatText("密 碼"));
tv3.setText("再次確認密碼");
tv4.setText(AlignedTextUtils.formatText("個性簽名"));
tv5.setText(AlignedTextUtils.formatText("編不下去了"));
特別說明:文字中的“空格”一定要是全角模式下的空格,因為全角模式下漢子,數字,符號等所占比例是一致的。
2.關鍵工具類
~ 目前這個工具類支持2-6個數字的對齊(如果你有其他需求可以參照這個思路自行編寫)
/**
* 不同文字數目2端對齊工具類 (支持2-6個數字)
*
* @author yuhao
* @time 2016年6月28日 */
public class AlignedTextUtils {
private static int n = 0;// 原Str擁有的字符個數
private static SpannableString spannableString;
private static double multiple = 0;// 放大倍數
/**
* 對顯示的字符串進行格式化 比如輸入:出生年月 輸出結果:出正生正年正月
*/
public static String formatStr(String str) {
if (TextUtils.isEmpty(str)) {
return "";
}
n = str.length();
if (n >= 6) {
return str;
}
StringBuilder sb = new StringBuilder(str);
for (int i = n - 1; i > 0; i--) {
sb.insert(i, "正");
}
return sb.toString();
}
/**
* 對顯示字符串進行格式化 比如輸入:安正卓正機正器正人 輸出結果:安 卓 機 器 人
*
* @param str
* @return */
public static SpannableString formatText(String str){
if (TextUtils.isEmpty(str)) {
return null;
}
str = formatStr(str);
if (str.length()<=6){
return null;
}
spannableString = new SpannableString(str);
switch (n) {
case 2:
multiple = 4;
break;
case 3:
multiple = 1.5;
break;
case 4:
multiple = 0.66666666666666666666666666666666667;
break;
case 5:
multiple = 0.25;
break;
default:
break;
}
for (int i = 1; i < str.length(); i = i + 2)
{
spannableString.setSpan(new RelativeSizeSpan((float) multiple), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
}
3.實現思路詳解
~ TextView自帶有行間距可是并沒有字間距,所以我想到了利用SpannableString的RelativeSizeSpan和ForegroundColorSpan以及StringBuilder來模擬字間距的效果,相信看了下面這張圖,你就基本明白實現的原理了
原理圖
步驟一:轉換字符串
~
利用formatStr(String str)方法來格式化字符串,每隔一個字符插入一個字符,上面的工具類我寫的是“正”字,是為了顯示的更清楚。而這個“正”字的作用就是為了稱當字間距的作用。
代碼:
tv1.setText(AlignedTextUtils.formatStr("安卓初學者"));
效果:
轉換字符串后的效果
步驟二:修改“字間距”大小
~
經過上一步之后我們需要做的就是縮放“正”字,那么到底應該縮放多少呢?
抽象派的圖片
如上圖,雖說丑了點,但是可以明顯看出5個字的字符串是由6個字的字符串多出來的那個字符平分成4份,所以每一個字符的縮放比為1/4倍.
以此類推可以得出一個公式縮放倍數:
(6-n)/(n-1)
代碼:
spannableString.setSpan(new RelativeSizeSpan((float) multiple), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果:
縮放比例后的效果
步驟三:修改“字間距”顏色
~
隱藏字間距,將顏色設置和背景一致即可。
代碼:
spannableString.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), i, i + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果:
最終效果
4.后記
- 這個工具類,僅僅是提供一個思路,也可能存在很多問題,如果問題歡迎聯系我,大家一起完善。
- 目前的問題:23個字的時候,由于縮放倍數大于1,造成了文本框變大問題。解決方法是:用全角字符的“空格”將23個字的字符轉換成5個字的字符
- 如果不是很了解SpannableString可以參考碼農小阿飛的《用SpannableString打造絢麗多彩的文本顯示效果》