当前位置: 首页 > 知识库问答 >
问题:

编辑文本和输入筛选器导致重复文本

桓智敏
2023-03-14

我正在尝试实现一个编辑文本,将输入限制为仅 Alpha 字符 [A-Za-z]。

我从本文中的InputFilter方法开始。当我键入“a%”时,文本消失,如果我按退格键,文本为“a”。我尝试过过滤器函数的其他变体,比如使用正则表达式只匹配[a-Za-z],有时会看到疯狂的行为,比如重复字符,我会键入“a”,然后键入“b”,再键入“aab”,然后再键入“c”,再得到“aabaabc”,然后按退格键,得到“aaba abc”!

这是我迄今为止使用的不同方法的代码。

    EditText input = (EditText)findViewById( R.id.inputText );
    InputFilter filter = new InputFilter() {
        @Override
        public CharSequence filter( CharSequence source, int start, int end, Spanned dest, int dstart, int dend ) {
            //String data = source.toString();
            //String ret = null;
            /*
            boolean isValid = data.matches( "[A-Za-z]" );
            if( isValid ) {
                ret = null;
            }
            else {
                ret = data.replaceAll( "[@#$%^&*]", "" );
            }
            */
            /*
            dest = new SpannableStringBuilder();
            ret = data.replaceAll( "[@#$%^&*]", "" );
            return ret;
            */

            for( int i = start; i < end; i++ ) {
                if( !Character.isLetter( source.charAt( i ) ) ) {
                    return "";
                }
            }

            return null;
        }
    };
    input.setFilters( new InputFilter[]{ filter } );

我完全被这个难住了,所以这里的任何帮助都将不胜感激。

编辑:好的,我已经用InputFilter做了很多实验,并得出了一些结论,尽管没有解决问题的方法。请参阅下面我的代码中的注释。我现在要尝试Imran Rana的解决方案。

    EditText input = (EditText)findViewById( R.id.inputText );
    InputFilter filter = new InputFilter() {
        // It is not clear what this function should return!
        // Docs say return null to allow the new char(s) and return "" to disallow
        // but the behavior when returning "" is inconsistent.
        // 
        // The source parameter is a SpannableStringBuilder if 1 char is entered but it 
        // equals the whole string from the EditText.
        // If more than one char is entered (as is the case with some keyboards that auto insert 
        // a space after certain chars) then the source param is a CharSequence and equals only 
        // the new chars.
        @Override
        public CharSequence filter( CharSequence source, int start, int end, Spanned dest, int dstart, int dend ) {
            String data = source.toString().substring( start, end );
            String retData = null;

            boolean isValid = data.matches( "[A-Za-z]+" );
            if( !isValid ) {
                if( source instanceof SpannableStringBuilder ) {
                    // This works until the next char is evaluated then you get repeats 
                    // (Enter "a" then "^" gives "a". Then enter "b" gives "aab")
                    retData = data.replaceAll( "[@#$%^&*']", "" );
                    // If I instead always returns an empty string here then the EditText is blanked.
                    // (Enter "a" then "^" gives "")
                    //retData = "";
                }
                else { // source is instanceof CharSequence
                    // We only get here if more than 1 char was entered (like "& ").
                    // And again, this works until the next char is evaluated then you get repeats 
                    // (Enter "a" then "& " gives "a". Then enter "b" gives "aab")
                    retData = "";
                }
            }

            return retData;
        }
    };
    input.setFilters( new InputFilter[]{ filter } );

共有3个答案

谢善
2023-03-14

宾果,我找到问题了!

当我在EditText上使用android: cursorViable="false"时,start和dstart参数无法正确匹配。

start参数对我来说仍然总是0,但dstart参数也总是0,所以只要我使用.replaceAll(),它就可以工作。这与这篇帖子所说的相反,所以我不太明白为什么,但至少我现在可以构建一些有效的东西!

田兴怀
2023-03-14

修复重复文本,适用于所有Android版本:

public static InputFilter getOnlyCharactersFilter() {
    return getCustomInputFilter(true, false, false);
}

public static InputFilter getCharactersAndDigitsFilter() {
    return getCustomInputFilter(true, true, false);
}

public static InputFilter getCustomInputFilter(final boolean allowCharacters, final boolean allowDigits, final boolean allowSpaceChar) {
    return 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)) {
                    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) {
            if (Character.isLetter(c) && allowCharacters) {
                return true;
            }
            if (Character.isDigit(c) && allowDigits) {
                return true;
            }
            if (Character.isSpaceChar(c) && allowSpaceChar) {
                return true;
            }
            return false;
        }
    };
}

现在,您可以使用此文件管理器,如下所示:

 //Accept Characters Only
edit_text.setFilters(new InputFilter[]{getOnlyCharactersFilter()});

//Accept Digits and Characters
edit_text.setFilters(new InputFilter[]{getCharactersAndDigitsFilter()});

//Accept Digits and Characters and SpaceBar
edit_text.setFilters(new InputFilter[]{getCustomInputFilter(true,true,true)});
楚嘉玉
2023-03-14
EditText input = (EditText) findViewById(R.id.inputText);
   input.addTextChangedListener(new TextWatcher() {

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // TODO Auto-generated method stub
         for( int i = start;i<s.toString().length(); i++ ) {
             if( !Character.isLetter(s.charAt( i ) ) ) {
                input.setText("");
             }
         }

    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        // TODO Auto-generated method stub

    }

    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub

    }
   });
 input.addTextChangedListener(new TextWatcher() {

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // TODO Auto-generated method stub

    }

    public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {
        // TODO Auto-generated method stub

    }
    public void afterTextChanged(Editable s) {
        // TODO Auto-generated method stub
         for( int i = 0;i<s.toString().length(); i++ ) {
             if( !Character.isLetter(s.charAt( i ) ) ) {                    
                s.replace(i, i+1,"");               
             }
         }
    }
   });
 类似资料:
  • 我一直在像这样限制我的编辑文本的输入; 但是任何使用过这种方法的人都会知道,当它与自动更正和退格键混合使用时,会导致重复字符。为了解决这个问题,我像这样从键盘上删除了自动更正栏; 现在,这在现有的Android键盘上运行良好,但问题是在替代键盘上(来自Google play),它不禁用自动更正,因此我再次遇到重复字符的问题。有人遇到过这个问题吗/知道如何解决吗?

  • 我正在开发一个Android聊天应用程序。一切运作良好,但除了一件事;我想设置一个布局的可见性消失,然后设置一个不同的布局可见时,用户开始输入编辑文本,就像在WhatsApp上实现的。但是我似乎想不明白。任何帮助都将不胜感激 基本上,我想做的是设置一个布局的可见性,该布局包含一个图像按钮,用于将图像上载到gone,然后显示一个布局,该布局包含一个图像按钮,用于在用户开始键入时将edittext中的

  • 我一直有一些来自EditText的奇怪行为的问题。setSelect,我希望你们都能帮忙! 我正在开发的应用程序有一个搜索字段,需要让它的行为非常类似于浏览器的搜索栏。例如,如果用户键入“fo ”,我们希望EditText自动完成“foobar ”,并突出显示自动完成的“obar”文本,以便在自动完成的文本与用户想要键入的内容不匹配时,用户可以很容易地替换它。 为了实现这一点,我设置了一个带有Te

  • 我使用p:编辑器作为输入: 我将此输入显示为: 但显示时选择了以下编辑器选项:;span style=“font-family:Verdana、Arial、Helvetica、sans-serif;font-size:13px;线宽:18px;背景色:rgb(255、255、255);” 为什么会发生这种情况,如何禁用这些?

  • EDIT--显示对象类,在initialize方法中添加代码,删除以前的filter方法,并从FXML中删除TextField的OnAction。--- 我第一次试图解决这个问题的尝试导致了许多Android问题,所以我在这里。 我使用JavaFX、Scenebuilder和FXML制作了一个简单的GUI。这个GUI模拟工厂车间的库存,可以从添加到/删除/显示/保存到文件。它还应该根据用户在中输入

  • 我想在用户在EditText中键入文本时将文本放入我的应用程序中的某个字符串中,并使用它来生动地在活动上显示它(在不同的视图中...) - 就像谷歌的实时/即时搜索工作一样...