创建扩展ASCII字符输入过滤器。

4
我正在使用以下InputFilter来过滤掉无效字符(ASCII十进制值大于127),当输入无效字符时,EditText会显示文本两次。但我希望EditText只显示有效字符。以下是发生的情况示例:
- 用户在EditText组件中输入XYZ€。 - 屏幕上出现Toast消息,指出“非ASCII字符无效”。 - EditText组件在屏幕上显示xyz,这正是我的预期。 - 用户输入一个有效字符A,因此屏幕显示XYZA。 - InputFilter运行并返回XYZA,但EditText组件中出现了XYZXYZA,这是不正确的。它重复了XYZ。
你有什么想法,为什么处理无效字符后会重复输入的文本?
屏幕截图:
<EditText android:id="@+id/editText"
    android:layout_width="fill_parent" android:layout_height="120dp"
    android:layout_marginTop="10dp" android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp" android:maxLength="45"
    android:focusable="true" android:inputType="text"
    android:cursorVisible="true" android:imeOptions="actionDone"
 />

活动:

public class EditTextActivity extends Activity {        

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        EditText eText = (EditText) findViewById(R.id.editText);
        setAsciiTextFilter();
    }    

    private void setAsciiTextFilter() {

              InputFilter filter = new InputFilter() {

                    int asciiNo;

                    @Override
                    public CharSequence filter(CharSequence source, int start, int end,
                            Spanned dest, int dstart, int dend) {

                        for (int i = start; i < end; i++) {

                            asciiNo = source.charAt(i);

                            if(asciiNo > 127) {       

                                toast = mUtility.showToast("Invalid non-Ascii Character", Toast.LENGTH_SHORT);

                                //Replace the invalid ascii character with empty String
                                return source.toString().replace(source.charAt(i)+"", "");
                            }    
                        }
                        return null;
                    }
                };


           eText.setFilters(new InputFilter[]{filter}); 
    }
}

新尝试:

 InputFilter filter = 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);
                                    int ascii = currentChar;
                                     if (ascii > 127) {    
                                         sourceAsSpannableBuilder.delete(i, i+1);
                                         toast = mUtility.showToast("Invalid non-Ascii Character", Toast.LENGTH_SHORT);
                                     }     
                                }
                                return source;
                            } else {
                                StringBuilder filteredStringBuilder = new StringBuilder();
                                for (int i = 0; i < end; i++) { 
                                    char currentChar = source.charAt(i);
                                    int ascii = currentChar;
                                    if (ascii <= 127) {    
                                        filteredStringBuilder.append(currentChar);
                                    }     
                                }
                                return filteredStringBuilder.toString();
                            }
                        }
                    };
2个回答

2
我认为最好使用一个for循环和答案。
另外请注意,在SpannableStringBuilder构造函数中传递source非常重要,以便从源中复制跨度。如果不这样做,那么事情就会变得混乱。
    @Override
    public CharSequence filter(CharSequence source, int start,
            int end, Spanned dest, int dstart, int dend) {
        SpannableStringBuilder ret;

        if (source instanceof SpannableStringBuilder) {
            ret = (SpannableStringBuilder)source;
        } else {
            ret = new SpannableStringBuilder(source);
        }

        for (int i = end - 1; i >= start; i--) {
            char currentChar = source.charAt(i);
            char currentChar = source.charAt(i);
            int ascii = currentChar;
            if (ascii > 127) {    
                ret.delete(i, i+1);
                toast = mUtility.showToast("Invalid non-Ascii Character", Toast.LENGTH_SHORT);
            }     
        }

        return ret;
    }

1

编辑:

我认为问题在于你返回了整个字符串,而你应该只返回该字符的替换内容。filter()会在文本更改时运行,并不一定在EditText中替换整个字符串。你需要注意这一点,以免把整个字符串塞到一个字符的位置。

这个问题是相关的(只需将非ASCII字符替换为非字母数字字符),那里的答案得到了广泛认可,所以你应该能够使用它来获得你想要的结果。

对于混乱的回答/删除事情,我感到很抱歉。我在离开家之前回答了这个问题。几分钟后,我意识到我的逻辑有一个严重的缺陷,所以我用手机删除了它。我讨厌在手机上尝试打出完整的答案,所以只能等一会儿。


1
感谢您的回答。我使用了您建议的方法并更新了我的代码(在“新尝试”部分)。一旦输入无效字符,即使输入有效字符,Toast也会继续显示,因为sourceAsSpannableBuilder.delete(i, i+1);每次都会删除无效字符。尽管EditText不显示它,但sourceAsSpannableBuilder似乎仍然保留着无效字符。有没有办法只在输入无效字符时显示Toast?感谢您的所有帮助... - c12
1
如果(end == i+1){ //显示toast }可以工作。 - c12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接