Android帶分隔符的輸入手機號碼的EditText
阿新 • • 發佈:2018-12-13
當用戶輸入手機號碼時,有些應用為了介面更加優美,要求輸入的手機號帶上分隔符,一般為344型的手機號碼,本文為封裝了帶分隔符的輸入手機號碼的自定義SeparatorPhoneEditText。
執行效果截圖如下:
程式碼如下,註釋在程式碼裡:
import android.content.Context; import android.support.v7.widget.AppCompatEditText; import android.text.Editable; import android.text.InputFilter; import android.text.InputType; import android.text.TextUtils; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; /** * 帶分隔符的手機號碼的EditView */ public class SeparatorPhoneEditView extends AppCompatEditText implements TextWatcher { private final int MAX_INPUT_LENGTH = 13;//允許最大輸入長度為11+2,考慮兩個佔位符佔的位數 private final char SEPARATOR = ' ';//分隔符,一般為-或半形空格 private StringBuilder mBuilder = new StringBuilder(); private int mChangeCount; public SeparatorPhoneEditView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SeparatorPhoneEditView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { requestFocus(); //設定鍵盤輸入模式 setInputType(InputType.TYPE_CLASS_NUMBER); //設定最大輸入長度 setFilters(new InputFilter[]{new InputFilter.LengthFilter(MAX_INPUT_LENGTH)}); addTextChangedListener(this); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mChangeCount = count - before; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { //當只有輸入數字時才進行調整 if (mChangeCount > 0 && !TextUtils.equals(s, mBuilder.toString())) { mBuilder.delete(0, mBuilder.length()); //因為在setText會重置為0,所以要在setText前記錄游標的位置 int cursorIndex = getSelectionStart(); int length = s.length(); for (int i = 0; i < length; i++) { char c = s.charAt(i); if (c != SEPARATOR) { mBuilder.append(c); } if ((isSeparationPosition(mBuilder.length()))) { mBuilder.append(SEPARATOR); } } //可能會得到大於最大長度的字串,將最後一個刪除 if (mBuilder.length() > MAX_INPUT_LENGTH) { mBuilder.delete(MAX_INPUT_LENGTH, mBuilder.length()); } //計算游標的偏移量 int offset = calculateOffset(s, cursorIndex); setText(mBuilder.toString()); //游標位置,做最小值判斷是為防止越界,也是為了調整游標位 setSelection(Math.min(cursorIndex + offset, mBuilder.length())); } Log.i(SeparatorPhoneEditView.class.getSimpleName(), "getPhoneCode:" + getPhoneCode()); } /** * 計算游標位之前需要的偏移量 */ private int calculateOffset(Editable s, int cursorIndex) { int length = s.length(); int offset = 0;//需要偏移的游標位數,負數表示向前調,正數表示向後偏移 int adjustedLen = mBuilder.length();//調整後長度 int minLen = adjustedLen > length ? length : adjustedLen; for (int i = 0; i < minLen; i++) { if (i > cursorIndex - 1) break; char c = s.charAt(i); char adjustedChar = mBuilder.charAt(i); //只需要考慮調整後字元型別不同的情況 if (c == SEPARATOR && adjustedChar != SEPARATOR) { offset--; } else if (c != SEPARATOR && adjustedChar == SEPARATOR) { offset++; } } return offset; } /** * 是否分隔位置 */ private boolean isSeparationPosition(int index) { final int NUMBER_FRONT = 3;//前面有幾位數 final int NUMBER_MIDDLE = 4;//中間有幾位數 final int SECOND_SEPARATOR_POSITION = NUMBER_FRONT + NUMBER_MIDDLE + 1;//第二個空位的位置 return index == NUMBER_FRONT || index == SECOND_SEPARATOR_POSITION; } public String getPhoneCode() { Editable text = getText(); return text == null ? null : text.toString().replace(String.valueOf(SEPARATOR), ""); } }