package com.example.sequencenumber; import android.content.Context; import android.content.res.TypedArray; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; import android.view.View; import android.widget.EditText; /** * 分割輸入框 * * @author Administrator * */ public class DivisionEditText extends EditText { /* 內容數組 */ private String[] text; /* 數組實際長度 (內容+分隔符) */ private Integer length; /* 容許輸入的長度 */ private Integer totalLength; /* 每組的長度 */ private Integer eachLength; /* 分隔符 */ private String delimiter; /* 佔位符 */ private String placeHolder; public DivisionEditText(Context context) { super(context); } public DivisionEditText(Context context, AttributeSet attrs) { super(context, attrs); try { // 初始化屬性 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.EditText); this.totalLength = typedArray.getInteger( R.styleable.EditText_totalLength, 0); this.eachLength = typedArray.getInteger( R.styleable.EditText_eachLength, 0); this.delimiter = typedArray .getString(R.styleable.EditText_delimiter); if (this.delimiter == null || this.delimiter.length() == 0) { this.delimiter = "-"; } this.placeHolder = typedArray .getString(R.styleable.EditText_placeHolder); if (this.placeHolder == null || this.placeHolder.length() == 0) { this.placeHolder = " "; } typedArray.recycle(); // 初始化 init(); // 內容變化監聽 this.addTextChangedListener(new DivisionTextWatcher()); // 獲取焦點監聽 this.setOnFocusChangeListener(new DivisionFocusChangeListener()); } catch (Exception e) { e.printStackTrace(); } } public DivisionEditText(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } /** * 初始化 */ public void init() { // 總共分幾組 int groupNum = 0; // 若是每組長度(除數)不爲0,計算 if (this.eachLength != 0) { groupNum = this.totalLength / this.eachLength; } // 實際長度 length = this.totalLength + this.eachLength != 0 ? this.totalLength + groupNum - 1 : 0; // 初始化數組 text = new String[this.length]; // 若是數組大小大於0,初始化裏面內容 // 空格佔位,分隔符佔位 if (length > 0) { for (int i = 0; i < length; i++) { if (i != 0 && (i + 1) % (this.eachLength + 1) == 0) { text[i] = this.delimiter; } else { text[i] = placeHolder; } } // 設置文本 mySetText(); // 設置焦點 mySetSelection(); } } /** * 獲取結果 * * @return */ public String getResult() { StringBuffer buffer = new StringBuffer(); for (String item : text) { if (!placeHolder.equals(item) && !delimiter.equals(item)) { buffer.append(item); } } return buffer.toString(); } /** * 文本監聽 * * @author Administrator * */ private class DivisionTextWatcher implements TextWatcher { @Override public void afterTextChanged(Editable s) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // 若是當前長度小於數組長度,認爲使用退格 if (s.length() < length) { // 光標所在位置 int index = DivisionEditText.this.getSelectionStart(); // 刪除的字符 String deleteStr = text[index]; // 若是是分隔符,刪除分隔符前一個 if (delimiter.equals(deleteStr)) { index--; } // 置空 text[index] = placeHolder; // 查看前一個是否爲分隔符 if (index - 1 >= 0) { if (delimiter.equals(text[index - 1])) { index--; } } // 設置文本 mySetText(); // 設置焦點 mySetSelection(index); } // 只能一個一個字符輸入 if (count == 1) { // 從光標起始,是否還有空的位置 int index = isBlank(DivisionEditText.this.getSelectionStart()); // 若是還有 if (index != -1) { // 輸入框內的字符串 String allStr = s.toString(); // 輸入的字符串 String inputStr = allStr.substring(start, start + count); // 替換佔位符 text[index] = inputStr; } // 設置文本 mySetText(); // 設置焦點 mySetSelection(); } } } /** * 獲取焦點監聽 * * @author Administrator * */ private class DivisionFocusChangeListener implements OnFocusChangeListener { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { // 設置焦點 mySetSelection(0); } } } /** * 設置文本 * * @param text */ private void mySetText() { StringBuffer buffer = new StringBuffer(); for (String item : text) { buffer.append(item); } // 設置文本 setText(buffer); } /** * 設置焦點 * * @param text */ private void mySetSelection() { mySetSelection(fullSelection()); } /** * 設置焦點 * * @param text */ private void mySetSelection(int index) { DivisionEditText.this.setSelection(index); } /** * 從光標位置起始,檢查後面是否還有空的佔位符 * * @param text * @param selection * @return */ private int isBlank(int selection) { int index = -1; for (int i = selection - 1; i < length; i++) { if (placeHolder.equals(text[i])) { index = i; break; } } return index; } /** * 最後一個不空的字符後的光標位置 * * @param text * @return */ private int fullSelection() { int index = 0; for (int i = 0; i < length; i++) { if (!placeHolder.equals(text[i]) && !delimiter.equals(text[i])) { index = i + 1; } } return index; } public Integer getTotalLength() { return totalLength; } public void setTotalLength(Integer totalLength) { this.totalLength = totalLength; } public Integer getEachLength() { return eachLength; } public void setEachLength(Integer eachLength) { this.eachLength = eachLength; } public String getDelimiter() { return delimiter; } public void setDelimiter(String delimiter) { this.delimiter = delimiter; } public String getPlaceHolder() { return placeHolder; } public void setPlaceHolder(String placeHolder) { this.placeHolder = placeHolder; } }
attrs.xmljava
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="EditText"> <!-- 總共輸入長度 --> <attr name="totalLength" format="integer" /> <!-- 每組的長度 --> <attr name="eachLength" format="integer" /> <!-- 分隔符 --> <attr name="delimiter" format="string" /> <!-- 佔位符 --> <attr name="placeHolder" format="string" /> </declare-styleable> </resources>
在佈局文件中使用android
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:fsms="http://schemas.android.com/apk/res/com.example.sequencenumber" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.sequencenumber.DivisionEditText android:layout_width="match_parent" android:layout_height="wrap_content" fsms:delimiter="-" fsms:eachLength="5" fsms:placeHolder="0" fsms:totalLength="25" /> </LinearLayout>