Android EditText上的InputFilter导致重复文本

Android EditText上的InputFilter导致重复文本,android,android-edittext,android-input-filter,Android,Android Edittext,Android Input Filter,我正在尝试实现一个EditText,它将输入限制为仅包含数字的大写字符[A-Z0-9] 我从一些帖子开始使用InputFilter方法,但在这里我遇到了三星Galaxy Tab 2的一个问题,而不是emulator或Nexus 4 问题是这样的: 当我输入“A”时,文本显示为“A”,这很好 现在当我输入“B”时,文本应该是“AB”,但它会给我“AAB” 这看起来很奇怪 简言之,它重复字符 以下是我正在使用的代码: public class DemoFilter implements InputF

我正在尝试实现一个
EditText
,它将输入限制为仅包含数字的大写字符[A-Z0-9]

我从一些帖子开始使用InputFilter方法,但在这里我遇到了三星Galaxy Tab 2的一个问题,而不是emulator或Nexus 4

问题是这样的:

  • 当我输入“A”时,文本显示为“A”,这很好
  • 现在当我输入“B”时,文本应该是“AB”,但它会给我“AAB” 这看起来很奇怪
  • 简言之,它重复字符

    以下是我正在使用的代码:

    public class DemoFilter implements InputFilter {
    
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
                int dend) {
    
            if (source.equals("")) { // for backspace
                return source;
            }
            if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints
                                                            // here
            {
                return source.toString().toUpperCase();
            }
            return "";
        }
    }
    
    XML文件代码:

    <EditText
        android:id="@+id/et_licence_plate_1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:hint="0"
        android:imeOptions="actionNext"
        android:inputType="textNoSuggestions"
        android:maxLength="3"
        android:singleLine="true"
        android:textSize="18px" >
    </EditText>
    
    
    
    我对这一点非常感兴趣,因此在此提供的任何帮助都将不胜感激。

    可以附加到可编辑的,以约束对其所做的更改。 它强调所做的更改,而不是它包含的全部文本

    如下所述

     public class DemoFilter implements InputFilter {
    
            public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart,
                    int dend) {
    
                if (source.equals("")) { // for backspace
                    return source;
                }
                if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints
                                                                // here
                {
                   char[] ch = new char[end - start];
    
                  TextUtils.getChars(source, start, end, ch, 0);
    
                    // make the characters uppercase
                    String retChar = new String(ch).toUpperCase();
                    return retChar;
                }
                return "";
            }
        }
    
    试试这个:

    class CustomInputFilter implements InputFilter {
        StringBuilder sb = new StringBuilder();
    
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            Log.d(TAG, "filter " + source + " " + start + " " + end + " dest " + dest + " " + dstart + " " + dend);
            sb.setLength(0);
            for (int i = start; i < end; i++) {
                char c = source.charAt(i);
                if (Character.isUpperCase(c) || Character.isDigit(c) || c == ' ') {
                    sb.append(c);
                } else
                if (Character.isLowerCase(c)) {
                    sb.append(Character.toUpperCase(c));
                }
            }
            return sb;
        }
    }
    
    类CustomInputFilter实现InputFilter{
    StringBuilder sb=新的StringBuilder();
    @凌驾
    公共CharSequence筛选器(CharSequence源、int开始、int结束、跨区目标、int开始、int结束){
    Log.d(标记,“过滤器”+源+“”+开始+“”+结束+“目的地”+目的地+“”+dstart+“”+dend);
    sb.设定长度(0);
    for(int i=start;i

    当filter()方法一次接受多个字符(例如从剪贴板粘贴的文本)时,这也允许进行筛选。字符重复的问题来自InputFilter错误的实现。如果替换不应更改,则返回null:

    @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, end, null, sp, 0);
                return sp;
            } else {
                return sb;
            }           
        }
    }
    
    private boolean isCharAllowed(char c) {
        return Character.isUpperCase(c) || Character.isDigit(c);
    }
    
    @覆盖
    公共CharSequence筛选器(CharSequence源、int开始、int结束、跨区目标、int开始、int结束){
    布尔值keepOriginal=true;
    StringBuilder sb=新的StringBuilder(结束-开始);
    for(int i=start;i
    我也遇到了同样的问题,在使用此处发布的解决方案修复后,带有autocomplete的键盘仍然存在一个问题。一种解决方案是将inputType设置为“visiblePassword”,但这会减少功能,不是吗

    filter()
    方法中返回非空结果时,使用调用

    TextUtils.copySpansFrom((Spanned) source, start, newString.length(), null, newString, 0);
    

    这将自动完成范围复制到新结果中,并修复了在选择自动完成建议时重复出现的奇怪行为。

    我在Android的InputFilter中发现了许多错误,我不确定这些是错误还是有意的。但肯定不符合我的要求。所以我选择使用TextWatcher而不是InputFilter

    private String newStr = "";
    
    myEditText.addTextChangedListener(new TextWatcher() {
            @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) {
                String str = s.toString();
                if (str.isEmpty()) {
                    myEditText.append(newStr);
                    newStr = "";
                } else if (!str.equals(newStr)) {
                    // Replace the regex as per requirement
                    newStr = str.replaceAll("[^A-Z0-9]", "");
                    myEditText.setText("");
                }
            }
    
            @Override
            public void afterTextChanged(Editable s) {
                // Do nothing
            }
        });
    

    上述代码不允许用户在EditText中键入任何特殊符号。只允许使用大写字母数字字符。

    以下解决方案还支持自动完成键盘选项

    editTextFreeNote.addTextChangedListener( new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                String newStr = s.toString();
                newStr = newStr.replaceAll( "[a-zA-Z0-9 ]*", "" );
                if(!s.toString().equals( newStr )) {
                    editTextFreeNote.setText( newStr );
                    editTextFreeNote.setSelection(editTextFreeNote.getText().length());
                }
            }
    
            @Override
            public void afterTextChanged(Editable s) {}
        } );
    

    对我来说也是一样,
    InputFilter
    复制字符。这就是我所用的:

    Kotlin
    版本:

    private fun replaceInvalidCharacters(value: String) = value.replace("[a-zA-Z0-9 ]*".toRegex(), "")
    
    textView.addTextChangedListener(object : TextWatcher {
        override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
    
        override fun afterTextChanged(s: Editable) {}
    
        override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
            val newValue = replaceInvalidCharacters(s.toString())
            if (newValue != s.toString()) {
                textView.setText(newValue)
                textView.setSelection(textView.text.length)
            }
        }
    })
    

    工作正常。

    这个问题我以前遇到过好几次。 在xml中设置某些类型的输入类型可能是问题的根源。 要在
    InputFilter
    TextWatcher
    中解决此问题,无需任何附加逻辑,只需在代码中设置输入类型,而不是xml,如下所示:


    editText.setInputType(getInputType()| InputType.TYPE_TEXT_FLAG_NO_建议)

    最近我遇到了同样的问题 问题的原因是。。。如果输入字符串中没有更改,则不返回源字符串返回null,某些设备无法正确处理此问题,这就是重新绘制字符的原因

    在您的代码中返回

    return source.toString().toUpperCase();
    
    不返回此,
    返回null
    代替
    返回source.toString().toUpperCase(),但这将是一个修补程序,它不会处理所有场景,对于所有场景,您都可以使用此代码

    public class SpecialCharacterInputFilter implements InputFilter {
    
        private static final String PATTERN = "[^A-Za-z0-9]";
        // if you want to allow space use this pattern
        //private static final String PATTERN = "[^A-Za-z\\s]";
    
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            // Only keep characters that are letters and digits
            String str = source.toString();
            str = str.replaceAll(PATTERN, AppConstants.EMPTY_STRING);
            return str.length() == source.length() ? null : str;
        }
    }
    

    在这段代码中发生了什么,有一个正则表达式,通过它我们将找到除字母和数字以外的所有字符,现在它将用空字符串替换所有字符,然后剩余的字符串将有字母和数字。

    Huh,我检查了这里发布的代码,它的工作与预期一样,您是否也可以发布editText的xml文件实现,在其中添加此DemoFilter..在我的示例中,它也可以在nexus 4和emulator上正常工作。但没有三星Galax标签2的工作。当“键盘设置”中的“建议”处于禁用状态时,它将在选项卡2上工作。因此,xml布局文件中的任何属性都可以强制停止建议。这是正确的。请参阅InputFilter.AllCaps的实现,它会复制此处显示的结果文本。您可以尝试android:inputType=“textVisiblePassword”来禁用自动完成,这是InputFilter的真正问题。这不是正确的方法,但它确实有效。干杯你的解决方案有效!需要注意的是,这个问题只出现在安卓7上,而不出现在安卓6或安卓8上(至少在我的应用程序上)。@MartinoLessio you Sir刚刚用这个为我节省了很多时间comment@MartinoLessio,它起作用了。你能解释一下原因吗