Відповіді:
Я знайшов це на іншому форумі. Працює як чемпіон.
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 });
InputFilter
s трохи складніші в версіях Android, які відображають пропозиції зі словника. Ви інколи отримуєте параметр a SpannableStringBuilder
, іноді просту String
в source
параметрі.
Наступне InputFilter
має працювати. Сміливо вдосконалюйте цей код!
new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
if (source instanceof SpannableStringBuilder) {
SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder)source;
for (int i = end - 1; i >= start; i--) {
char currentChar = source.charAt(i);
if (!Character.isLetterOrDigit(currentChar) && !Character.isSpaceChar(currentChar)) {
sourceAsSpannableBuilder.delete(i, i+1);
}
}
return source;
} else {
StringBuilder filteredStringBuilder = new StringBuilder();
for (int i = start; i < end; i++) {
char currentChar = source.charAt(i);
if (Character.isLetterOrDigit(currentChar) || Character.isSpaceChar(currentChar)) {
filteredStringBuilder.append(currentChar);
}
}
return filteredStringBuilder.toString();
}
}
}
String replacement = source.subSequence(start, end).toString(); return replacement.replaceAll("[^A-Za-z0-9_\\-@]", "");
source instanceof SpannableStringBuilder
введення АБ дає мені ААБ, як при спробі попередньої відповіді. На щастя, мені вдалося обійти це за допомогою рішення @florian нижче.
набагато простіше:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
між ними. Ви можете використовувати щось подібне"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
тощо.
Жодна з опублікованих відповідей не працювала для мене. Я прийшов із власним рішенням:
InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
boolean keepOriginal = true;
StringBuilder sb = new StringBuilder(end - start);
for (int i = start; i < end; i++) {
char c = source.charAt(i);
if (isCharAllowed(c)) // put your condition here
sb.append(c);
else
keepOriginal = false;
}
if (keepOriginal)
return null;
else {
if (source instanceof Spanned) {
SpannableString sp = new SpannableString(sb);
TextUtils.copySpansFrom((Spanned) source, start, sb.length(), null, sp, 0);
return sp;
} else {
return sb;
}
}
}
private boolean isCharAllowed(char c) {
return Character.isLetterOrDigit(c) || Character.isSpaceChar(c);
}
}
editText.setFilters(new InputFilter[] { filter });
EditText
вже можуть мати власні фільтри, наприклад фільтр довжини. Тож замість того, щоб просто змінити фільтри, ви, швидше за все, хочете додати свої фільтри до вже існуючих.
Використовуйте цю свою роботу на 100% своїх потреб і дуже просто.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
В strings.xml
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Щоб уникнути спеціальних символів типу введення
public static InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String blockCharacterSet = "~#^|$%*!@/()-'\":;,?{}=!$^';,?×÷<>{}€£¥₩%~`¤♡♥_|《》¡¿°•○●□■◇◆♧♣▲▼▶◀↑↓←→☆★▪:-);-):-D:-(:'(:O 1234567890";
if (source != null && blockCharacterSet.contains(("" + source))) {
return "";
}
return null;
}
};
Ви можете встановити фільтр для редагування тексту, як показано нижче
edtText.setFilters(new InputFilter[] { filter });
На додаток до прийнятої відповіді також можна використовувати, наприклад: android:inputType="textCapCharacters"
як атрибут <EditText>
, щоб прийняти лише великі символи (і цифри).
Чомусь конструктор класу android.text.LoginFilter має обсяг пакету, тому ви не можете прямо розширити його (навіть якщо це було б ідентично цьому коду). Але ви можете продовжити LoginFilter.UsernameFilterGeneric! Тоді у вас є тільки це:
class ABCFilter extends LoginFilter.UsernameFilterGeneric {
public UsernameFilter() {
super(false); // false prevents not-allowed characters from being appended
}
@Override
public boolean isAllowed(char c) {
if ('A' <= c && c <= 'C')
return true;
if ('a' <= c && c <= 'c')
return true;
return false;
}
}
Це насправді не задокументовано, але воно є частиною основної лібрики, і джерело є простим . Я використовую його деякий час зараз, до цих пір жодних проблем, хоча, зізнаюся, я не намагався робити щось складне, пов’язане з гайковими ключами.
Це правильно, найкращий спосіб вирішити це, щоб виправити це в самому макеті XML, використовуючи:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
як справедливо зазначає Флоріан Фреліх, він добре працює навіть для перегляду тексту.
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Просто слово обережності, символи, згадані у android:digits
заповіті, будуть відображатися лише тому, будьте обережні, щоб не пропустити жодного набору символів :)
inputType
не впливає на фільтрацію.
Це просте рішення працювало для мене, коли мені потрібно було запобігти введенню порожніх рядків у EditText. Ви, звичайно, можете додати більше символів:
InputFilter textFilter = new InputFilter() {
@Override
public CharSequence filter(CharSequence c, int arg1, int arg2,
Spanned arg3, int arg4, int arg5) {
StringBuilder sbText = new StringBuilder(c);
String text = sbText.toString();
if (text.contains(" ")) {
return "";
}
return c;
}
};
private void setTextFilter(EditText editText) {
editText.setFilters(new InputFilter[]{textFilter});
}
Якщо ви підклас InputFilter, ви можете створити свій власний InputFilter, який би відфільтрував будь-які символи, що не належать до альфа-чисел.
Інтерфейс InputFilter має один метод, filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
і він надає вам всю інформацію, яку вам потрібно знати про те, яким символам було введено в EditText, якому він призначений.
Після створення власного InputFilter ви можете призначити його EditText, зателефонувавши setFilters (...).
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text.Spanned, int, int)
Ігноруючи прольотні речі, якими мали справу інші люди, щоб правильно обробити пропозиції словника, я виявив, що наступний код працює.
Джерело зростає, коли пропозиція зростає, тому ми повинні подивитися, скільки символів насправді очікують, що ми замінимо, перш ніж щось повернути.
Якщо у нас немає недійсних символів, поверніть null, щоб відбулася заміна за замовчуванням.
В іншому випадку нам потрібно витягнути дійсні символи з підрядки, яка НЕЗАЄМО буде розміщена в 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;
}
};
щоб запобігти словам у тексті редагування. створити клас, який ти можеш використовувати будь-коли.
public class Wordfilter implements InputFilter
{
@Override
public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) {
// TODO Auto-generated method stub
boolean append = false;
String text = source.toString().substring(start, end);
StringBuilder str = new StringBuilder(dest.toString());
if(dstart == str.length())
{
append = true;
str.append(text);
}
else
str.replace(dstart, dend, text);
if(str.toString().contains("aaaaaaaaaaaa/*the word here*/aaaaaaaa"))
{
if(append==true)
return "";
else
return dest.subSequence(dstart, dend);
}
return null;
}
}
Спочатку додайте strings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
Код в Котліні:
edit_text.filters += InputFilter { source, start, end, _, _, _ ->
val mask = getString(R.string.vin_code_mask)
for (i in start until end) {
if (!mask.contains(source[i])) {
return@InputFilter ""
}
}
null
}
Дивно, але це дивно працює на м'якій клавіатурі емулятора.
Увага! Наступний код буде фільтрувати всі літери та інші символи, крім цифр для клавіатур програмного забезпечення. На смартфонах з’явиться лише цифрова клавіатура.
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Я також , як правило , встановлюється maxLength
, filters
, inputType
.
Це стара тема, але всі розроблені рішення мають проблеми (залежно від пристрою / версії Android / клавіатури).
РІЗНИЙ ПІДХІД
Таким чином , в кінці кінців , я пішов з іншим підходом, замість того щоб використовувати InputFilter
проблемну реалізацію, я використовую TextWatcher
і TextChangedListener
зEditText
.
ПОВНИЙ КОД (ПРИКЛАД)
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
}
});
Причина InputFilter
- не гарне рішення в Android, оскільки це залежить від реалізації клавіатури. Вхід з клавіатури фільтрується до передачі входу до EditText
. Але, оскільки деякі клавіатури мають різні реалізації для InputFilter.filter()
виклику, це проблематично.
З іншого боку, TextWatcher
це не стосується реалізації клавіатури, вона дозволяє нам створити просте рішення і бути впевненим, що воно буде працювати на всіх пристроях.
onTextChanged
Просто необхідно public void
перед ним.
Я зробив щось подібне, щоб зробити це просто:
edit_text.filters = arrayOf(object : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
return source?.subSequence(start, end)
?.replace(Regex("[^A-Za-z0-9 ]"), "")
}
})
Таким чином ми замінюємо всі небажані символи в новій частині вихідного рядка порожньою.
edit_text
Змінної є EditText
об'єкт , який ми маємо в виду.
Код записаний на kotlin
.
Можна використовувати setOnKeyListener
. У цьому методі ми можемо налаштувати вхід edittext
!
Ось так я створив фільтр для поля "Ім'я" в редагуванні тексту. (Перша літера - це CAPS, і після кожного слова дозволяється лише один пробіл.
public void setNameFilter() {
InputFilter filter = new InputFilter() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (dend == 0) {
if (Character.isSpaceChar(source.charAt(i)) ||
!Character.isAlphabetic(source.charAt(i))) {
return Constants.Delimiter.BLANK;
} else {
return String.valueOf(source.charAt(i)).toUpperCase();
}
} else if (Character.isSpaceChar(source.charAt(i)) &&
String.valueOf(dest).endsWith(Constants.Delimiter.ONE_SPACE)) {
return Constants.Delimiter.BLANK;
} else if ((!Character.isSpaceChar(source.charAt(i)) &&
!Character.isAlphabetic(source.charAt(i)))) {
return Constants.Delimiter.BLANK;
}
}
return null;
}
};
editText.setFilters(new InputFilter[]{filter, new InputFilter.LengthFilter(Constants.Length.NAME_LENGTH)});
}
Я маю таку ж відповідь у Котліні:
/**
* Returns the filter of the editText'es CharSequence value when [filterType] is:
* 1 -> letters; 2 -> letters and digits; 3 -> digits;
* 4 -> digits and dots
*/
class InputFilterAlphanumeric(private val filterType: Int): InputFilter {
override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int): CharSequence {
(source as? SpannableStringBuilder)?.let {sourceAsSpannableBuilder ->
for (i in (end - 1) downTo start) {
val currentChar = source[i]
when(filterType) {
1 -> {
if (!currentChar.isLetter() && !currentChar.isWhitespace()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
2 -> {
if (!currentChar.isLetterOrDigit() && !currentChar.isWhitespace()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
3 -> {
if (!currentChar.isDigit()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
4 -> {
if (!currentChar.isDigit() || !currentChar.toString().contains(".")) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
}
}
return source
} ?: run {
val filteredStringBuilder = StringBuilder()
for (i in start until end) {
val currentChar = source?.get(i)
when(filterType) {
1 -> {
if (currentChar?.isLetter()!! || currentChar.isWhitespace()) {
filteredStringBuilder.append(currentChar)
}
}
2 -> {
if (currentChar?.isLetterOrDigit()!! || currentChar.isWhitespace()) {
filteredStringBuilder.append(currentChar)
}
}
3 -> {
if (currentChar?.isDigit()!!) {
filteredStringBuilder.append(currentChar)
}
}
4 -> {
if (currentChar?.isDigit()!! || currentChar.toString().contains(".")) {
filteredStringBuilder.append(currentChar)
}
}
}
}
return filteredStringBuilder
}
}
}
і отримати клас з функцією Extension:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}