如何使用InputFilter限制Android中EditText中的字符?

Tim*_*yne 168 android android-edittext

我想将字符限制为0-9,az,AZ和空格键.设置inputtype我可以限制为数字,但我无法弄清楚Inputfilter查看文档的方式.

moo*_*ese 180

我在另一个论坛上找到了这个.像冠军一样工作.

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 });
Run Code Online (Sandbox Code Playgroud)

  • 实际上它在新的Androids(如4.0+)中不起作用.他们在键盘上方引入字典建议.当你输入一个常用词(比如说"the")后面跟着这个过滤器的非法字符(比如说" - ")时,整个单词就会被删除,然后输入另一个字符(即使是允许的字符,比如"blah")过滤器返回""并且字段中不显示任何字符.这是因为该方法在source参数中获取了一个SpannableStringBuilder,其中包含"the-blah",以及跨越整个输入字符串的start/end参数...请参阅我的答案以获得更好的解决方案. (55认同)
  • 在该示例中,它返回"",我认为它应该返回应该显示的文本.即你应该删除非法字符并返回你想要显示的字符串.http://developer.android.com/reference/android/widget/TextView.html#onKeyUp(int,android.view.KeyEvent) (4认同)

Łuk*_*mek 133

在Android版本中,InputFilters有点复杂,可以显示字典建议.有时你会得到一个SpannableStringBuilder,有时候InputFilter参数中有一个普通的String .

以下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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这没有考虑重复字典建议文本出现的问题.@serwus在答案中确定了这一点.基本上,如果在两种情况下都没有进行修改,则应返回null. (3认同)
  • 这段代码完美如lukasz所说(在上面的答案中),但我面临着非词典单词的一些问题.当我键入chiru它显示3次像chiruchiruchiru.怎么解决?它也占用了白色空间但是如何限制下一个白色空间? (3认同)
  • 出于某种原因,当`source instanceof SpannableStringBuilder`时,输入_AB_会在尝试上一个答案时给我_AAB_.幸运的是,我可以使用下面的@florian解决方案解决它. (3认同)
  • 有没有理由你不想对源进行后续处理?你是否认为这样做有什么不妥(为了只允许使用字母数字和一些特殊字符):`String replacement = source.subSequence(start,end).toString(); return replacement.replaceAll("[^ A-Za-z0-9 _ \\ - @]","");` (2认同)

小智 104

更容易:

<EditText
    android:inputType="text"
    android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
Run Code Online (Sandbox Code Playgroud)

  • 不是多语种解决方案 (23认同)
  • 令人敬畏的解决方案只想添加你不需要在其间给出"",".你可以使用这样的东西`"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM" (17认同)
  • 虽然这似乎是一个完美的答案,但根据文档存在一个问题:"对于KeyListener的所有实现,此类仅涉及硬件键盘.软件输入方法没有义务触发此类中的方法." 我认为InputFilter可能是一个更好的,虽然更复杂的方式. (8认同)
  • 不适合我,android 4.3,三星galaxy nexus. (3认同)

Kam*_*ryn 67

发布的答案都没有对我有用.我带来了自己的解决方案:

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 });
Run Code Online (Sandbox Code Playgroud)

  • 唯一的,`EditText`已经有了自己的过滤器,例如长度过滤器.因此,您不仅要覆盖过滤器,而且还希望将过滤器添加到现有过滤器中. (4认同)
  • 这是唯一一个实际上有正确方法来防止从字典建议中重复文本的答案!给予好评! (3认同)
  • 这个答案(或Android的输入机制的工作方式)的一个小问题是,退格有时对用户来说似乎不起作用,因为退格是对仍保留在源缓冲区中的先前输入的无效字符进行退格。 (2认同)

Moh*_*him 23

使用它的工作100%你的需要,非常简单.

<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
Run Code Online (Sandbox Code Playgroud)

在strings.xml中

<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Run Code Online (Sandbox Code Playgroud)


小智 15

避免输入类型中的特殊字符

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;
    }
};
Run Code Online (Sandbox Code Playgroud)

您可以将过滤器设置为您的编辑文本,如下所示

edtText.setFilters(new InputFilter[] { filter });
Run Code Online (Sandbox Code Playgroud)

  • 不阻止这些字符中的任何一个。㋡ ㋛ ☺ ☹ ☻ 〠 シッツヅ Ü 〲 〴 ϡ ﭢ ت ⍡ ⍢ ⍣ ⍤ ⍥ ⍨ ⍩ ὃ ὕ ὣ э (2认同)

Coo*_*ind 8

首先添加到strings.xml

<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
Run Code Online (Sandbox Code Playgroud)

XML

android:digits="@string/vin_code_mask"
Run Code Online (Sandbox Code Playgroud)

Kotlin代码:

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
}
Run Code Online (Sandbox Code Playgroud)

奇怪,但它在模拟器的软键盘上工作得很奇怪。

警告!以下代码将过滤软件键盘除数字之外的所有字母和其他符号。智能手机上只会出现数字键盘。

edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Run Code Online (Sandbox Code Playgroud)

我也经常设置maxLength,,filtersinputType


小智 7

除了接受的答案之外,还可以使用例如:android:inputType="textCapCharacters"作为<EditText>仅接受大写字符(和数字)的属性.

  • android:inputType ="textCapCharacters"不限制使用其他字符,如'., - "等. (5认同)

Laz*_*zar 7

我做了这样的事情来保持简单:

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 ]"), "")
    }
})
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我们将源字符串的新部分中的所有不需要的字符替换为空字符串。

edit_text变量是EditText我们所指的对象。

代码是用kotlin.


Yar*_*nko 7

您可以在正则表达式中指定所需的字符并在 InputFilter 中使用它:

val regex = Regex("[a-zA-Z\\d ]")
    
editText.filters = arrayOf(InputFilter { source, _, _, _, _, _ ->
    source.filter { regex.matches(it.toString()) }
})
Run Code Online (Sandbox Code Playgroud)

注意,我没有使用\w字符类,因为它包含下划线_


Gro*_*oxx 5

由于某种原因,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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这并没有真正记录,但它是核心库的一部分,而且源代码很简单.我已经使用它一段时间了,到目前为止没有任何问题,但我承认我没有尝试做任何涉及spannables的复杂事情.


Kai*_*las 5

这是正确的,最好的方法是使用以下方法在XML布局中修复它:

<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Run Code Online (Sandbox Code Playgroud)

正如FlorianFröhlich正确指出的那样,它甚至适用于文本视图.

<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Run Code Online (Sandbox Code Playgroud)

请注意,android:digits只会显示遗嘱中提到的字符,所以请注意不要错过任何一组字符:)