Reputation: 2499
I am developing an application for keyboard, but i am geting an issue. I want to restrict/block some special character from soft keyboard in EditText in android programmatically.
So, Is there any way I can restrict any special character input in edit text in android?
Upvotes: 82
Views: 111602
Reputation: 81
This is very simple to restrict any key from virtual input inside EditText. We achieve this with XML or JAVA/Kotlin. Below is the code with XML:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:digits="abcdefghijklmnopqrstuvwxyzA BCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n\u0020"
android:singleLine="true"
android:textColor="@color/black" />
Above code for Name Field restricts all the special characters. We Show another example for a Description/Message/Feedback.
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine"
android:digits=".,?:/abcdefghijklmnopqrstuvwxyzA BCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n\u0020"
android:singleLine="false"
android:textColor="@color/black" />
That means simply adding digits which are included.
Upvotes: 0
Reputation: 163
kotlin version of this answer
class NameActivity : AppCompatActivity() {
var myFilter = InputFilter { source, _, _, _, _, _ ->
try {
val c = source[0]
return@InputFilter if (Character.isLetterOrDigit(c) || c == '_' || c == '.' || c == ' ')
c.toString()
else
""
} catch (e: Exception) { }
null
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_name)
val edittext = findViewById<EditText>(R.id.edittext)
edittext.filters = (arrayOf(myFilter))
}
}
Upvotes: 0
Reputation: 614
Can be solved by using filters
, i.e.
val regex = Regex("^[~#^|$%&*!]*$")
val filter = InputFilter { source, _, _, _, _, _ ->
return@InputFilter when {
source?.matches(regex) == true -> ""
else -> null
}
}
editText.filters = arrayOf(filter)
and for handling copy-pasted
text, can be done by adding condition to check if text inputted was greater than 1
, which now looks like this
val regex = Regex("^[~#^|$%&*!]*$")
val filter = InputFilter { source, _, _, _, _, _ ->
return@InputFilter when {
source?.matches(regex) == true -> ""
source.length > 1 -> source.trim { it.toString().matches(regex) } // Put your desired logic here, these sample logic was doing a trim/remove
else -> null
}
}
editText.filters = arrayOf(filter)
Upvotes: 0
Reputation: 2215
The accepted answer still allows the user paste in unwanted characters. This solution works:
All you have to do is this:
List<String> unwantedChars = new ArrayList<>(Arrays.asList("@", "€"));
editText.addTextChangedListener(new FilterUnwantedChars(editText, unwantedChars));
Helper class:
public class FilterUnwantedChars implements TextWatcher {
private List<String> unwantedChars;
private EditText editText;
private boolean listenToTextChange;
public FilterUnwantedChars(EditText editText, List<String> unwantedChars) {
this.unwantedChars = unwantedChars;
this.editText = editText;
this.listenToTextChange = true;
}
@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 (!listenToTextChange) {
listenToTextChange = true;
return;
}
String result = s.toString();
final String oldString = result;
for (String unwanted : unwantedChars) {
result = result.replace(unwanted, "");
}
if (!oldString.equals(result)) {
listenToTextChange = false;
int currentPos = editText.getSelectionStart()-1;
editText.setText(result);
try {
editText.setSelection(currentPos);
} catch (Exception e) {
// nothing
}
}
}
@Override
public void afterTextChanged(Editable s) { }
public void setEditText(EditText editText) {
this.editText = editText;
}
public EditText getEditText() {
return editText;
}
public List<String> getUnwantedChars() {
return unwantedChars;
}
public void setUnwantedChars(List<String> unwantedChars) {
this.unwantedChars = unwantedChars;
}
}
Upvotes: 1
Reputation: 29
This works for me...
android:digits="÷×=%_-+#().,abcdefghijklmnopqrstuvwxyzA BCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\n\u0020"
for space use:
\u0020
for new line use:
\n
for ime options use:
android:singleLine="true"
android:maxLines="1"
Hope it works for you...
Upvotes: 1
Reputation: 28484
Try this may work for you
public class MainActivity extends Activity {
private EditText editText;
private String blockCharacterSet = "~#^|$%&*!";
private InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && blockCharacterSet.contains(("" + source))) {
return "";
}
return null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
editText.setFilters(new InputFilter[] { filter });
}
}
Upvotes: 110
Reputation: 3847
Unfortunately the accepted solution doesn't work in all the cases. The proper solution would be to use the following InputFilter
:
private InputFilter filter = new InputFilter() {
// An example pattern that restricts the input only to the lowercase letters
private static final Pattern restrictedChars = Pattern.compile("[a-z]*")
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
final CharSequence replacementText = source.subSequence(start, end);
final CharSequence replacedText = dest.subSequence(dstart, dend);
if (source == null || restrictedChars.matcher(replacementText).matches()) {
return null; // Accept the original replacement
}
return replacedText; // Keep the original text
}
};
This solution differs from the accepted one in that it solves the following problems:
Upvotes: 0
Reputation: 3627
you can prevent for typing special character:
yourEditText.addTextChangedListener(new TextWatcher() {
CharSequence previous;
public void afterTextChanged(Editable s) {
if(s.toString().contains("&^%$#*&(")){
s.clear();
s.append(previous.toString());
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
previous = s;
}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
Upvotes: 2
Reputation: 389
First need to add DigitsKeyListener for allowing characters and then setRawInputType to edittext field
edit_field.setKeyListener(DigitsKeyListener.getInstance("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
edit_field.setRawInputType(InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
Upvotes: 5
Reputation: 536
For those who might be facing issues while adding space please add a blank space with all the alphabets. Below is an example Also you should know that user won't be able to add a new line in this case.
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="text"
android:digits="0123456789,a bcdefghijklmnopqrstuvwxyz"
android:maxLines="1"
android:singleLine="true" />
Upvotes: 6
Reputation: 526
If you want to add spaces you can give space after the last digit.
android:digits="0123456789qwertzuiopasdfghjklyxcvbnm "
Upvotes: 45
Reputation: 2648
Its late but may be helpfull for others. Instead of programaticaly, you can go with xml attribute. It may be the case that in Single layout you have many editText, out of which you wanna restrict special characters only in one EditText. So defining in xml will help you out. Here is the code to restrict special Characters by allowing them to only enter alphabets and numbers like below
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/text10"
android:singleLine="true"
android:maxLines="1"
android:maxLength="16"
android:digits="abcdefghijklmnopqrstuvwxyz0123456789"/>
Upvotes: 16
Reputation: 694
This should work:
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});
Or if you prefer the easy way:
<EditText android:inputType="text" android:digits="0123456789*,qwertzuiopasdfghjklyxcvbnm" />
Upvotes: 30