InputFilter is an Android SDK interface that allows intercepting and modifying input text before it is displayed in EditText. The developer sets filtering rules: allowed characters, maximum length, input format. According to Android Developers, 2026, InputFilter is used to restrict input of letters, digits, special characters and to automatically format text. Unlike TextWatcher, the filter triggers before the text changes, preventing invalid input at the source level.
Key Takeaways
InputFilter is a functional interface from the android.text package that defines a single method filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend). It is called automatically every time a user attempts to type, paste, or replace text in EditText. The return value determines whether the change will be accepted, rejected, or modified.
The main purpose of InputFilter is preventing invalid input before the text enters the field. For example, in a phone number digit input field, a filter can block letters and special characters. In a password field, it can enforce a minimum length. In a verification code field, it can allow only digits. Unlike validation through TextWatcher, the filter prevents erroneous characters from ever appearing on screen.
According to Android Developers, InputFilter is used in all Material Design components for TextInputEditText. Libraries like PhoneNumberFormattingTextWatcher combine TextWatcher and InputFilter for full formatting. It is recommended to use InputFilter as the first barrier of defense against invalid input, and TextWatcher for additional post-input logic.
The filter method receives six parameters: source — the input text, start and end — the bounds of the input fragment, dest — the current field content, dstart and dend — the insertion position. If the method returns null, the change is accepted unchanged. If it returns an empty string “”, the change is blocked. If it returns a new CharSequence, the original text is replaced with the returned value.
For example, if a user tries to type the letter “a” in a field that only allows digits, the filter returns “”, and the character does not appear. If “123” is entered, the filter might return “1-2-3”, adding separators. This mechanism enables automatic formatting of phone numbers, dates, and other structured data without TextWatcher.
Important: InputFilter does not modify the original data source, it only returns a filtered version. Android itself applies the returned value to Editable. If the filter returns null, no additional actions are required. If it returns modified text, Android removes the original range and inserts the new one.
Android SDK provides several built-in implementations of InputFilter. The most common is InputFilter.LengthFilter, which limits the maximum text length. The constructor accepts an integer — the maximum number of characters. If the current text length plus input exceeds the limit, the filter returns a truncated string, preventing the limit from being exceeded.
Also available is InputFilter.AllCaps, which converts all input characters to uppercase. It is used in fields for codes, postal codes, and other data where case matters. The filter does not simply block lowercase letters but converts them, which is convenient for the user — they see the result of the conversion.
There is InputFilter.LengthFilter for multiple limits — through a combination of filters. For example, if you need to limit the length to 20 characters and allow only digits, you can apply LengthFilter + a custom digit filter. Each filter executes sequentially, and the result of the previous one becomes the dest for the next.
| Filter | Purpose | Usage Example |
|---|---|---|
| LengthFilter | Text length restriction | Name field up to 50 characters |
| AllCaps | Uppercase conversion | Postal code field |
| Custom InputFilter | Arbitrary filtering rules | Digits only, special characters prohibited |
To create a custom filter, you need to implement the InputFilter interface and override the filter method. A common task is a filter that allows only digits. In this case, the method checks each character from source using Character.isDigit and returns a filtered string or null if all characters are valid.
class DigitsInputFilter : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
val sb = StringBuilder()
for (i in start until end) {
val c = source?.get(i)
if (c != null && Character.isDigit(c)) {
sb.append(c)
}
}
return if (sb.length == end - start) null else sb
}
}
An example DigitsInputFilter iterates through all characters of the input text and keeps only digits. If all characters pass the check, the method returns null — this is the optimal case as it requires no additional memory operations. If some characters are discarded, a new string is returned, and only digits end up in EditText.
Another popular scenario is a filter to block special characters. The implementation is similar: checking each character via Character.isLetterOrDigit or comparing against a list of allowed characters. Such filters are used in username fields, search strings, and other places where special characters are not allowed.
Filters are set on EditText via the setFilters(InputFilter[]) method. The filter array replaces the current ones, so if you need to add a filter to existing ones, you must retrieve the current filters via getFilters(), create a new array, and set it back. EditText has one default filter — LengthFilter, which is set via android:maxLength in XML.
val editText = findViewById<EditText>(R.id.phone_input)
editText.filters = arrayOf(
DigitsInputFilter(),
InputFilter.LengthFilter(10)
)
In the example, two filters are set: DigitsInputFilter (digits only) and LengthFilter (max 10 characters). The order of filters in the array matters: the first filter receives the original input, processes it, and passes the result to the second. If DigitsInputFilter filters out some characters, LengthFilter sees the already filtered text and applies its length restriction to it.
Filters can also be set via the XML attribute android:inputType, which automatically adds some filters. For example, inputType=“phone” adds DigitsKeyListener and allows only digits and some special characters. However, for full control over filtering, it is recommended to use setFilters programmatically, especially when combining multiple rules.
InputFilter and TextWatcher perform different functions and are often used together. InputFilter works at the input level — it prevents invalid characters from entering the field. TextWatcher works after input — it allows reacting to changes, performing complex validation rules, and updating the UI. The combination of both approaches yields the best result.
For example, for an email input field: InputFilter can block spaces and Cyrillic characters at the input level, while TextWatcher can check full email pattern compliance after each change. The first protects against obvious errors, the second against structural ones. This separation of responsibilities makes the code cleaner and reduces the validation load.
According to Material Design Guidelines, filters should be applied to fields with strict constraints: phone numbers, verification codes, PIN codes, postal codes. For fields with soft validation — name, address, comment — TextWatcher alone is sufficient to avoid hindering users from entering legitimate but non-standard values.
| Criterion | InputFilter | TextWatcher |
|---|---|---|
| Trigger moment | Before text change | After text change |
| Purpose | Block invalid characters | React to changes, validation, UI |
| Return value | Filtered text or null | None (void) |
| Application | setFilters() | addTextChangedListener() |
Frequently Asked Questions
InputFilter intercepts input before the text changes and can block or modify it. TextWatcher is called after the change and allows reacting to the new value. InputFilter is preventive protection, TextWatcher is post-processing. For full form validation, it is recommended to use both approaches.
Pass an array of filters to the setFilters() method. Filters execute sequentially in array order. To avoid losing existing filters, retrieve them via getFilters(), add new ones to a copy of the array, and set it back via setFilters. Do not overwrite filters without considering already installed ones.
Yes, InputFilter can modify input by returning a modified CharSequence. For example, a phone number filter can add spaces or parentheses. However, for complex formatting, it is better to combine InputFilter with TextWatcher, since the filter is focused on blocking rather than post-processing.
Any characters: spaces, letters, digits, special characters, Unicode characters. In a custom filter, you define the condition using Character.isLetter, isDigit, isWhitespace, or compare against a blacklist/whitelist. The filter can allow only Latin, only Cyrillic, or only a specific set of characters.
No, InputFilter only triggers on user input or clipboard paste. If text is set programmatically via setText(), filters are not applied. For checking programmatic text, use TextWatcher validation or explicit checks before setting.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also