最近碰到一個(gè)UI層面的需求——要求TextView內(nèi)容最多顯示一行且超過7個(gè)字時(shí)結(jié)尾顯示省略號(hào)砰逻。大家在拿到這個(gè)需求之后禾乘,基本都會(huì)寫出在xml中寫出下面的代碼來實(shí)現(xiàn)渊胸。
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1" 或者 android:singleLine="true"
android:maxEms="7"
android:ellipsize="end" />
上面的邏輯很清晰瞬铸,先設(shè)置最大行數(shù)為1斯撮,然后最大字?jǐn)?shù)為7经伙,最后超出時(shí)在結(jié)尾展示省略號(hào)。但是N鸸E聊ぁ!你會(huì)發(fā)現(xiàn)在某些機(jī)型上面是ok的溢十,但是在某些機(jī)型上面字?jǐn)?shù)計(jì)算錯(cuò)誤垮刹。然后一頓百度,發(fā)現(xiàn)大家在實(shí)現(xiàn)類似功能時(shí)都用的類似代碼张弛,但自己實(shí)現(xiàn)就是有問題荒典。后來一想酪劫,莫非是這個(gè)maxEms的原因?然后去官網(wǎng)查了一下API釋義:
也就是說通過maxEms設(shè)置TextView的屬性并不是指的該view的最大顯示字?jǐn)?shù)是7個(gè)寺董,而是該view最大寬度是7個(gè)EM的寬度覆糟,這里EM指的是印刷排版中英文字體M所占的寬度,也就是說并不是需求中所需要的字符的寬度遮咖。有關(guān)于maxEms的屬性介紹滩字,大家感興趣可以看下下面這篇文章:
http://www.reibang.com/p/8c6ddebbf4f2?utm_source=oschina-app
既然maxEms拿不準(zhǔn),那么用maxLength實(shí)現(xiàn)嗎御吞?答案也是否定的麦箍,如果使用了maxLength屬性,那么當(dāng)超出指定字符數(shù)后會(huì)直接截?cái)喽伙@示省略號(hào)陶珠,而且該屬性將漢字挟裂、英文、數(shù)字都算為一個(gè)字符揍诽。同樣的话瞧,使用maxWidth限制TextView的寬度也是行不通的。
系統(tǒng)方法無法實(shí)現(xiàn)產(chǎn)品需求寝姿,那么只能自己造輪子實(shí)現(xiàn)了交排。該需求主要有以下幾個(gè)點(diǎn)需要注意:1、最多顯示7個(gè)字饵筑;2埃篓、超出7個(gè)字進(jìn)行截?cái)嗖⒃谀┪诧@示省略號(hào);3根资、中文是兩個(gè)字符架专,其他都按一個(gè)字符算,也就是說例如“12.4萬人”的字?jǐn)?shù)應(yīng)該計(jì)算為 4 而不是 6 玄帕。下面貼一下自己的代碼:
private static String regEx = "[\u4e00-\u9fa5]"; // 中文范圍
/**
* 格式化字符串
* @param string 原始輸入字符串
* @param maxCount 最大字符限制部脚,中文算作2個(gè)字符,其他都算1個(gè)字符
* @return
*/
private static String formatText(String string, int maxCount) {
if ( (string == null || string.length() == 0)
&& getChCount(string) > maxCount) {
string = subStrByLen(string, maxCount - 1);
}
return string;
}
/**
*
* 截取字符串裤纹,超出最大字?jǐn)?shù)截?cái)嗖@示"..."
* @param str 原始字符串
* @param length 最大字?jǐn)?shù)限制(以最大字?jǐn)?shù)限制7個(gè)為例委刘,當(dāng)含中文時(shí),length應(yīng)設(shè)為2*7鹰椒,不含中文時(shí)設(shè)為7)
* @return 處理后的字符串
*/
public static String subStrByLen(String str, int length) {
if (str == null || str.length() == 0) {
return "";
}
int chCnt = getStrLen(str);
// 超出進(jìn)行截?cái)嗵幚? if (chCnt > length) {
int cur = 0;
int cnt = 0;
StringBuilder sb = new StringBuilder();
while (cnt <= length && cur < str.length()) {
char nextChar = str.charAt(cur);
if (isChCharacter(String.valueOf(nextChar))) {
cnt += 2;
} else {
cnt++;
}
if (cnt <= length) {
sb.append(nextChar);
} else {
return sb.toString() + "...";
}
cur++;
}
return sb.toString() + "...";
}
// 未超出直接返回
return str;
}
/**
* 獲取字符串中的中文字?jǐn)?shù)
*/
private static int getChCount(String str) {
int cnt = 0;
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(str);;
while(matcher.find()) {
cnt++;
}
return cnt;
}
/**
* 判斷字符是不是中文
*/
private static boolean isChCharacter(String str) {
if (str == null || str.length() == 0) {
return false;
}
if (str.length() > 1) {
return false;
}
return Pattern.matches(regEx, str);
}
/**
* 獲取字符長(zhǎng)度锡移,中文算作2個(gè)字符,其他都算1個(gè)字符
*/
public static int getStrLen(String str) {
if (str == null || str.length() == 0) {
return 0;
}
return str.length() + getChCount(str);
}
————————————————
版權(quán)聲明:本文為CSDN博主「CQURookie」的原創(chuàng)文章漆际,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議淆珊,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/Sky_327/article/details/103696970