android - EditText 长度过滤器无法正常工作 [英] android - EditText length filter not working as it should

查看:31
本文介绍了android - EditText 长度过滤器无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先我不得不说我在 SO 上阅读过类似的问题和答案,这个问题基本上是 这个问题 和许多其他问题,但这些问题的答案并不像我想要的那样工作.

First I have to say I have read similar questions and answers here on SO and this question is basically a duplicate of this question and many others but the answers given to those questions doesn't work like the way i want it.

问题:

像这样以编程方式在我的 EditText 上设置长度过滤器:

Setting length filter on my EditText programmatically like this:

editText.setFilters(new InputFilter[]{new LengthFilter(10)} );

它唯一能做的就是隐藏超出 EditText 限制的文本.它仍然在建议框中显示长(无限制)文本,我必须删除(退格)每个经过的字母,然后才能删除 EditText 中显示的内容.

The only thing it does is hide the text that go over the limit in the EditText. It still shows the long (unlimited) text in suggestion box and i have to delete (backspace) for each letter that go over before being able to delete what is shown in the EditText.

建议的解决方案:

  1. 将 InputType 设置为 textFilter.

    我以编程方式这样做:

  1. Setting InputType to textFilter.

    Programmatically I did this:

editText.setInputType( InputType.TYPE_TEXT_VARIATION_FILTER );

它隐藏了建议,但无限制的文本仍然存在,我仍然需要使用退格键来删除不应该存在的字母.

It hides suggestions but the unlimited text is still present and i still have to use backspace to delete letters that shouldn't be present.

将 InputType 设置为 textNoSuggestions|textVisiblePassword.

我以编程方式做到了这一点(也必须添加 TYPE_CLASS_TEXT 否则它不起作用):

Setting InputType to textNoSuggestions|textVisiblePassword.

Programmatically I did this (had to add TYPE_CLASS_TEXT too otherwise it wouldn't work):

editText.setInputType( InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD );

这个确实有效,但问题是它会停止手势输入"并将字体更改为等宽.

This one does work but the problem is it stops "gesture typing" and it changes the font to monospace.

更好的解决方案?
正如您所看到的,这两种方法在没有额外问题的情况下实际上是行不通的.有没有其他方法可以做到这一点,我错过了.如果我想保持手势输入和建议,我应该只使用 TextWatcher 吗?

推荐答案

我最终使用了 TextWatcher.我不确定这是否是最好的方法,但它确实适用于建议,并且不会关闭手势输入或更改字体样式.这是我的方法(我对 android 很陌生,所以如果这需要改进,请随时告诉我).

I ended up using a TextWatcher instead. I'm not sure if it is the best way to do this but it does work with suggestions and it doesn't turn off gesture typing or change the font style. Here's how I did it (I'm quite new to android so if this needs improvement feel free to let me know).

我在评论中添加了一个例子来阐明发生了什么.

I added an example in the comments to clarify what is going on.

创建这些全局变量:

private boolean mWatcherIsBlocked = false;
private String mBeforeChange;
private String mFilteredString; 
private int mCursorPosition = 0;

然后创建 TextWatcher 并将其添加到您的 EditText

Then create the TextWatcher and add it to your EditText

final int maxLength = 10; // desired length limit

/** 
 * lets say our EditText is showing "abcdefgh". We select "cdef" from it and 
 * paste a new text "ijklmnop" in the middle. What we should get according to
 * our maxLength is this: 
 * (1) "ab" (0th up to the letter from before_change_text we were selecting) + 
 * (2) "ijklmn" (part of the text we pasted minus the number of letters the whole 
 *      after_change_text goes over the 10 letter limit) + 
 * (3) "gh" (last part of before_change_text that wasn't selected)
 * 
 * so the new text has to be "abijkmngh"
 */

TextWatcher textWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // get before_change_text if textWatcher isn't blocked
        if (!mWatcherIsBlocked) mBeforeChange = s.toString();
    }
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        if (!mWatcherIsBlocked){
            // get after_change_text if textWatcher isn't blocked
            String after = s.toString();
            // if after_change_text's length is bigger than the limit 
            if (after.length() > maxLength) {
                // see how much it goes over the limit
                int over = after.length() - maxLength;
                // add parts (1) and (2) like our example above
                String st = mBeforeChange.substring(0, start) + // (1)
                            after.substring(start, start + count - over); // (2)
                // get where the cursor position should be after pasting (
                // = after the last letter we could paste = length of (1) + (2) )
                mCursorPosition = st.length();
                // now add part (3) of our text to the first two
                st += mBeforeChange.substring(
                          mBeforeChange.length() - (maxLength - st.length()), 
                          mBeforeChange.length());
                // now assign this new text to a global variable
                mFilteredString = st;
            } else { 
                // if after_change_text hasn't gone over the limit assign it 
                // directly to our global variable
                mFilteredString = s.toString();
            }
        }
    }
    @Override
    public void afterTextChanged(Editable s) {
        // if filtered text is not the same as unfiltered text 
        // or textWatcher is not blocked
        if (!mFilteredString.equals(s.toString()) && !mWatcherIsBlocked) {
            // block textWatcher to avoid infinite loops created by setText 
            // (this might not work as I well as I think!)
            mWatcherIsBlocked = true;
            // set new text to our EditText
            editText.setText(mFilteredString);
            // set its cursor position 
            editText.setSelection(mCursorPosition);
            // unblock the textWatcher
            mWatcherIsBlocked = false;
        }
    }
};

// add the TextWatcher to our EditText
editText.addTextChangedListener(textWatcher);

这篇关于android - EditText 长度过滤器无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆