Android實(shí)用技巧——UI展示之TextView超出某個(gè)字?jǐn)?shù)限制后顯示省略號(hào)

最近碰到一個(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奸汇,一起剝皮案震驚了整個(gè)濱河市施符,隨后出現(xiàn)的幾起案子往声,更是在濱河造成了極大的恐慌,老刑警劉巖戳吝,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浩销,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡骨坑,警方通過查閱死者的電腦和手機(jī)撼嗓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門柬采,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欢唾,“玉大人,你說我怎么就攤上這事粉捻〗盖玻” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵肩刃,是天一觀的道長(zhǎng)祟霍。 經(jīng)常有香客問我,道長(zhǎng)盈包,這世上最難降的妖魔是什么沸呐? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮呢燥,結(jié)果婚禮上崭添,老公的妹妹穿的比我還像新娘。我一直安慰自己叛氨,他們只是感情好呼渣,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寞埠,像睡著了一般屁置。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仁连,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天蓝角,我揣著相機(jī)與錄音,去河邊找鬼饭冬。 笑死帅容,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伍伤。 我是一名探鬼主播并徘,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扰魂!你這毒婦竟也來了麦乞?” 一聲冷哼從身側(cè)響起蕴茴,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎姐直,沒想到半個(gè)月后倦淀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡声畏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年撞叽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片插龄。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡愿棋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出均牢,到底是詐尸還是另有隱情糠雨,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布徘跪,位于F島的核電站甘邀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏垮庐。R本人自食惡果不足惜松邪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望哨查。 院中可真熱鬧逗抑,春花似錦、人聲如沸解恰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)护盈。三九已至挟纱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腐宋,已是汗流浹背紊服。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胸竞,地道東北人欺嗤。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像卫枝,于是被迫代替她去往敵國(guó)和親煎饼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容