最近項目中有個在EditText中輸入子網掩碼(xxx.xxx.xxx.xxx)形式的需求,只需
手動填入數字,自動添加”.”進去。於是想到了EditText的addTextChangedListener,
不過在editText.setText()時就碰到了問題,報了java.lang.StackOverflowError錯誤。
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
StringBuilder sb = new StringBuilder();//111.222.333.444
if (s == null || s.length() == 0) return;
for (int i = 0; i < s.length(); i++) {
if (i != 3 && i != 7 && i != 11 && s.charAt(i) == '.') {
continue;
} else {
sb.append(s.charAt(i));
if ((sb.length() == 4 || sb.length() == 8 || sb.length() == 12) && sb.charAt(sb.length() - 1) != '.') {
sb.insert(sb.length() - 1, ".");
}
}
}
editText.setText(sb.toString()); // 此處原因報錯
}
由於每次EditText有變動就會觸發onTextChanged(),就會一直遞歸 執行editText.setText();
造成當前線程棧滿了,就會使程序崩潰。
我們只要增加條件去中斷這種遞歸即可解決問題,不滿足條件就不執行。
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
StringBuilder sb = new StringBuilder();//111.222.333.444
if (s == null || s.length() == 0) return;
for (int i = 0; i < s.length(); i++) {
if (i != 3 && i != 7 && i != 11 && s.charAt(i) == '.') {
continue;
} else {
sb.append(s.charAt(i));
if ((sb.length() == 4 || sb.length() == 8 || sb.length() == 12) && sb.charAt(sb.length() - 1) != '.') {
sb.insert(sb.length() - 1, ".");
}
}
}
if (!sb.toString().equals(s.toString())) { //增加條件
editText.setText(sb.toString());
Log.d("Position", start + "/" + before + "/" + count + "/" + sb.toString() + "/" + s.toString());
}
}
當輸入1234時,Log日誌爲
D/Position: 0/3/4/123.4/1234
sb.toString()的值是123.4,而s.toString()的值是1234,兩個值不同纔會執行setText()方法。
總之,我們只需要提供一個遞歸出口就能解決問題。