最近项目中需要实现类似银行卡输入4位有空格的输入格式,在网上查找发现大部分的都有bug,虽然能实现,但是会出现各种bug(比如在中间删除,空格就你懂得了)。
没办法只能自己查找资料,研究代码。大部分人都是对edittext添加addTextChangedListener,监听textwatcher,但是这个监听要想明白,这个是edittext已经修改完成了,通知你的地方,并不能直接限制edittext的输入,所以我就想到了需要去edittext的源码看看。
研究了源码我们需要,重写edittext,在edittext的方法中有onCreateInputConnection方法,这个方法就是控制输入的能有效拦截输入的内容。
话不多说上代码:通过下述代码可以实现输入电话号自动空格,并且不能粘贴复制,可以在任意位置进行删除,插入,不会影响空格位置(网上大部分都不能实现),如果需要银行卡空格的设置,在这个基础上可以修改就是控制字符的位置即可。代码还实现了控制粘贴和复制的操作防止通过粘贴设置值导致出错
.............................
public class PhoneLimitEditText extends AppCompatEditText {
private static final String TAG = PhoneLimitEditText.class.getSimpleName();
private static final int NUM_13 = 13;
private static final int NUM_3 = 3;
private static final int NUM_7 = 7;
private static final int NUM_8 = 8;
private int tempSelect = 0;
private boolean isTextChange = false;
public PhoneLimitEditText(Context context) {
super(context);
init();
}
public PhoneLimitEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PhoneLimitEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
disableCopyAndPaste();
}
/**
* ime
*
* @param outAttrs
*/
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
return new mInputConnection(super.onCreateInputConnection(outAttrs), true);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
Log.i(TAG, "onTextChanged: " + text);
if (isTextChange) {
isTextChange = false;
return;
}
if (lengthBefore > 0) {
if (tempSelect <= text.length()) {
calcTabText(text);
}
} else if (lengthAfter > 0) {
if (getSelectionStart() < text.length()) {
calcTabText(text);
}
}
if (text.toString().endsWith(" ")) {
getEditableText().delete(text.length() - 1, text.length());
}
}
/**
* calc text add tab.
*
* @param text editText content.
*/
private void calcTabText(CharSequence text) {
isTextChange = true;
String tempText = text.toString().replace(" ", "");
StringBuilder stringBuilder = new StringBuilder(tempText);
if (tempText.length() > NUM_3) {
stringBuilder.insert(NUM_3, " ");
}
if (tempText.length() > NUM_7) {
stringBuilder.insert(NUM_8, " ");
}
getEditableText().replace(0, text.length(), stringBuilder);
setSelection(getEditableText().length());
}
class mInputConnection extends InputConnectionWrapper implements InputConnection {
public mInputConnection(InputConnection target, boolean mutable) {
super(target, mutable);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
if (" ".equals(text.toString())) {
return super.commitText("", newCursorPosition);
}
if (!text.toString().matches("[0-9]")) {
return false;
}
int length = getEditableText().length();
if (length == NUM_13) {
return false;
}
if (length == NUM_3 || length == NUM_8) {
text = " " + text;
}
return super.commitText(text, newCursorPosition);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_TAB) {
return false;
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
tempSelect = getSelectionStart();
}
}
return super.sendKeyEvent(event);
}
}
/**
* cancel copy & pause.
*/
public void disableCopyAndPaste() {
try {
setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return true;
}
});
setLongClickable(false);
setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// setInsertionDisabled when user touches the view
setInsertionDisabled();
}
return false;
}
});
setCustomSelectionActionModeCallback(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void setInsertionDisabled() {
try {
Field editorField = TextView.class.getDeclaredField("mEditor");
editorField.setAccessible(true);
Object editorObject = editorField.get(this);
// if this view supports insertion handles
Class editorClass = Class.forName("android.widget.Editor");
Field mInsertionControllerEnabledField =
editorClass.getDeclaredField("mInsertionControllerEnabled");
mInsertionControllerEnabledField.setAccessible(true);
mInsertionControllerEnabledField.set(editorObject, false);
// if this view supports selection handles
Field mSelectionControllerEnabledField =
editorClass.getDeclaredField("mSelectionControllerEnabled");
mSelectionControllerEnabledField.setAccessible(true);
mSelectionControllerEnabledField.set(editorObject, false);
} catch (Exception ex) {
ex.printStackTrace();
}
}}
......................................
感觉不错就点赞支持一下吧O(∩_∩)O~