I want to restrict the chars to 0-9, a-z, A-Z and spacebar only. Setting inputtype I can limit to digits but I cannot figure out the ways of Inputfilter looking through the
I found this on another forum. Works like a champ.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (!Character.isLetterOrDigit(source.charAt(i))) {
return "";
}
}
return null;
}
};
edit.setFilters(new InputFilter[] { filter });
Ignoring the span stuff that other people have dealt with, to properly handle dictionary suggestions I found the following code works.
The source grows as the suggestion grows so we have to look at how many characters it's actually expecting us to replace before we return anything.
If we don't have any invalid characters, return null so that the default replacement occurs.
Otherwise we need to extract out the valid characters from the substring that's ACTUALLY going to be placed into the EditText.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
boolean includesInvalidCharacter = false;
StringBuilder stringBuilder = new StringBuilder();
int destLength = dend - dstart + 1;
int adjustStart = source.length() - destLength;
for(int i=start ; i<end ; i++) {
char sourceChar = source.charAt(i);
if(Character.isLetterOrDigit(sourceChar)) {
if(i >= adjustStart)
stringBuilder.append(sourceChar);
} else
includesInvalidCharacter = true;
}
return includesInvalidCharacter ? stringBuilder : null;
}
};
In addition to the accepted answer, it is also possible to use e.g.: android:inputType="textCapCharacters"
as an attribute of <EditText>
in order to only accept upper case characters (and numbers).
Use this its work 100% your need and very simple.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
In strings.xml
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
much easier:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
This is an old thread, but the purposed solutions all have issues (depending on device / Android version / Keyboard).
DIFFERENT APPROACH
So eventually I went with a different approach, instead of using the InputFilter
problematic implementation, I am using TextWatcher
and the TextChangedListener
of the EditText
.
FULL CODE (EXAMPLE)
editText.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
super.afterTextChanged(editable);
String originalText = editable.toString();
int originalTextLength = originalText.length();
int currentSelection = editText.getSelectionStart();
// Create the filtered text
StringBuilder sb = new StringBuilder();
boolean hasChanged = false;
for (int i = 0; i < originalTextLength; i++) {
char currentChar = originalText.charAt(i);
if (isAllowed(currentChar)) {
sb.append(currentChar);
} else {
hasChanged = true;
if (currentSelection >= i) {
currentSelection--;
}
}
}
// If we filtered something, update the text and the cursor location
if (hasChanged) {
String newText = sb.toString();
editText.setText(newText);
editText.setSelection(currentSelection);
}
}
private boolean isAllowed(char c) {
// TODO: Add the filter logic here
return Character.isLetter(c) || Character.isSpaceChar(c);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Do Nothing
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Do Nothing
}
});
The reason InputFilter
is not a good solution in Android is since it depends on the keyboard implementation. The Keyboard input is being filtered before the input is passed to the EditText
. But, because some keyboards have different implementations for the InputFilter.filter()
invocation, this is problematic.
On the other hand TextWatcher
does not care about the keyboard implementation, it allows us to create a simple solution and be sure it will work on all devices.