【bug雜記1】限制EditText文本長(zhǎng)度

我到底想要干啥?

需求的本意是EditText只能輸入不超過(guò)一行的文字并且不會(huì)出現(xiàn)"…",所以簡(jiǎn)單使用singleLine來(lái)實(shí)現(xiàn)這個(gè)效果肯定不行,那么下一個(gè)思路就是通過(guò)添加TextWatcher對(duì)文本變化進(jìn)行監(jiān)聽(tīng),并且通過(guò)不斷measure文字的寬度并且不斷截取文字來(lái)使文字短到可以被控件顯示下,所以使用substring來(lái)實(shí)現(xiàn)這個(gè)需求,重點(diǎn)就在截取文字的代碼,所以我的第一版本是醬紫的

簡(jiǎn)單實(shí)現(xiàn)V0.9

public String adjustText(TextView textView, String text) {
    String tmpTxt = null;
    // 要求只能顯示一行的文字寬度不能換行
    if (textView != null && text != null) {
        // 為了避免substring刪除emoji等多個(gè)char的元素導(dǎo)致的錯(cuò)誤截取
        int codePointCount = text.codePointCount(0, text.length());
        for (int i = codePointCount; i >= 0; i--) {
            int offset = text.offsetByCodePoints(0, i);
            if (StringUtil.isEmpty((tmpTxt = text.substring(0, offset)))
                    || (textView.getPaint().measureText(tmpTxt) + textView.getPaddingLeft()
                    + textView.getPaddingRight()) < textView.getWidth()) {
                break;
            }
        }
    }
    return tmpTxt == null ? "" : tmpTxt;
}

簡(jiǎn)單測(cè)試了試了幾次,輸入中文或者英文字符乍一看是沒(méi)有問(wèn)題的,結(jié)果為了賣萌輸入了??這個(gè)emoji表情,就出現(xiàn)了亂碼,納尼?什么鬼??墒堑降资峭?

為啥用substring之后就亂碼了呢?

原來(lái)Java對(duì)于普通的字符char使用2個(gè)字節(jié)存儲(chǔ),而中文和emoji等使用2個(gè)char(4字節(jié))存儲(chǔ),但是substring是直接截取是針對(duì)單個(gè)char的,直接把emoji的char給人家截?cái)嗔?,?dāng)然就顯示亂碼嘍~

怎么解決亂碼問(wèn)題呢?

原因知道了,可是怎么解決呢。原來(lái)Java早就考慮到這種問(wèn)題啦,通過(guò)codePointCount可以獲取有效的代碼點(diǎn)。啥是代碼點(diǎn),理解為一個(gè)完整的字符(可能1個(gè)char,也可能2個(gè)char),比如一個(gè)emoji表情就認(rèn)為是一個(gè)代碼點(diǎn),通過(guò)offsetByCodePoints可以獲取第i個(gè)代碼點(diǎn)距離其實(shí)下標(biāo)的距離,通過(guò)substring就可以獲取正確的字符串啦,就不存在截取一半emoji的尷尬情況啦,整理下,代碼如下~

簡(jiǎn)單實(shí)現(xiàn)V1.0

public String adjustText(TextView textView, String text) {
    String tmpTxt = null;
    // 要求只能顯示一行的文字寬度不能換行
    if (textView != null && text != null) {
        // 為了避免substring刪除emoji等多個(gè)char的元素導(dǎo)致的錯(cuò)誤截取
        int codePointCount = text.codePointCount(0, text.length());
        for (int i = codePointCount; i >= 0; i--) {
            int offset = text.offsetByCodePoints(0, i);
            if (StringUtil.isEmpty((tmpTxt = text.substring(0, offset)))
                    || (textView.getPaint().measureText(tmpTxt) + textView.getPaddingLeft()
                    + textView.getPaddingRight()) < textView.getWidth()) {
                break;
            }
        }
    }
    return tmpTxt == null ? "" : tmpTxt;
}

這個(gè)情況處理完畢,處理完字符串的截取在onTextChanged方法中調(diào)用EditText的setText來(lái)實(shí)現(xiàn)截取(注意設(shè)置前一定要比較當(dāng)前的文本和設(shè)置的文本哦,不然就要StackOverFlow啦),尷尬的是又存在了另一個(gè)問(wèn)題,就是光標(biāo)問(wèn)題呀,不能每次截取都要把光標(biāo)移到最后面吧。所以通過(guò)設(shè)置前備份下光標(biāo)位置即可,代碼如下

int selectionStart = mEditText.getSelectionStart();
mEditText.setText(handledText);
mEditText
    .setSelection(selectionStart > mEditText.length() ? mEditText.length() : selectionStart);

啰嗦在最后

好吧,看著這么簡(jiǎn)單的一個(gè)需求被我寫出來(lái)好幾個(gè)bug,也是很無(wú)奈的說(shuō),果然程序員每天的工作就是寫bug呀,不管如何,藥別停 插一句,最愛(ài)婷婷媳婦啦~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容