How do I use InputFilter to limit characters in an EditText in Android?

后端 未结 20 1180
慢半拍i
慢半拍i 2020-11-22 04:23

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

相关标签:
20条回答
  • 2020-11-22 05:11

    First add into strings.xml:

    <string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
    

    XML:

    android:digits="@string/vin_code_mask"
    

    Code in 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
    }
    

    Strange, but it works weirdly on emulator's soft keyboard.

    Warning! The following code will filter all letters and other symbols except digits for software keyboards. Only digital keyboard will appear on smartphones.

    edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
    

    I also usually set maxLength, filters, inputType.

    0 讨论(0)
  • 2020-11-22 05:14

    InputFilters are a little complicated in Android versions that display dictionary suggestions. You sometimes get a SpannableStringBuilder, sometimes a plain String in the source parameter.

    The following InputFilter should work. Feel free to improve this code!

    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();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 05:15

    None of posted answers did work for me. I came with my own solution:

    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 });
    
    0 讨论(0)
  • 2020-11-22 05:16

    For some reason the android.text.LoginFilter class's constructor is package-scoped, so you can't directly extend it (even though it would be identical to this code). But you can extend LoginFilter.UsernameFilterGeneric! Then you just have this:

    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;
        }
    }
    

    This isn't really documented, but it's part of the core lib, and the source is straightforward. I've been using it for a while now, so far no problems, though I admit I haven't tried doing anything complex involving spannables.

    0 讨论(0)
  • 2020-11-22 05:16

    It is possible to use setOnKeyListener. In this method, we can customize the input edittext !

    0 讨论(0)
  • 2020-11-22 05:17

    To avoid Special Characters in input type

    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;
        }
    };
    

    You can set filter to your edit text like below

    edtText.setFilters(new InputFilter[] { filter });
    
    0 讨论(0)
提交回复
热议问题