我到底想要干啥?
需求的本意是EditText只能輸入不超過一行的文字并且不會出現"…",所以簡單使用singleLine來實現這個效果肯定不行,那么下一個思路就是通過添加TextWatcher對文本變化進行監聽,并且通過不斷measure文字的寬度并且不斷截取文字來使文字短到可以被控件顯示下,所以使用substring來實現這個需求,重點就在截取文字的代碼,所以我的第一版本是醬紫的
簡單實現V0.9
public String adjustText(TextView textView, String text) {
String tmpTxt = null;
// 要求只能顯示一行的文字寬度不能換行
if (textView != null && text != null) {
// 為了避免substring刪除emoji等多個char的元素導致的錯誤截取
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;
}
簡單測試了試了幾次,輸入中文或者英文字符乍一看是沒有問題的,結果為了賣萌輸入了??這個emoji表情,就出現了亂碼,納尼?什么鬼。可是到底是歪?
為啥用substring之后就亂碼了呢?
原來Java對于普通的字符char使用2個字節存儲,而中文和emoji等使用2個char(4字節)存儲,但是substring是直接截取是針對單個char的,直接把emoji的char給人家截斷了,當然就顯示亂碼嘍~
怎么解決亂碼問題呢?
原因知道了,可是怎么解決呢。原來Java早就考慮到這種問題啦,通過codePointCount可以獲取有效的代碼點。啥是代碼點,理解為一個完整的字符(可能1個char,也可能2個char),比如一個emoji表情就認為是一個代碼點,通過offsetByCodePoints可以獲取第i個代碼點距離其實下標的距離,通過substring就可以獲取正確的字符串啦,就不存在截取一半emoji的尷尬情況啦,整理下,代碼如下~
簡單實現V1.0
public String adjustText(TextView textView, String text) {
String tmpTxt = null;
// 要求只能顯示一行的文字寬度不能換行
if (textView != null && text != null) {
// 為了避免substring刪除emoji等多個char的元素導致的錯誤截取
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;
}
這個情況處理完畢,處理完字符串的截取在onTextChanged方法中調用EditText的setText來實現截?。ㄗ⒁庠O置前一定要比較當前的文本和設置的文本哦,不然就要StackOverFlow啦),尷尬的是又存在了另一個問題,就是光標問題呀,不能每次截取都要把光標移到最后面吧。所以通過設置前備份下光標位置即可,代碼如下
int selectionStart = mEditText.getSelectionStart();
mEditText.setText(handledText);
mEditText
.setSelection(selectionStart > mEditText.length() ? mEditText.length() : selectionStart);
啰嗦在最后
好吧,看著這么簡單的一個需求被我寫出來好幾個bug,也是很無奈的說,果然程序員每天的工作就是寫bug呀,不管如何,藥別停 插一句,最愛婷婷媳婦啦~