【问题标题】:android - EditText length filter not working as it shouldandroid - EditText 长度过滤器无法正常工作
【发布时间】:2018-02-19 15:21:58
【问题描述】:

首先我不得不说我已经在 SO 上阅读了类似的问题和答案,这个问题基本上是 this question 和许多其他问题的重复,但是对这些问题的答案并不像我想要的那样工作。

问题:

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

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

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

建议的解决方案:

  1. 将 InputType 设置为 textFilter。

    我以编程方式这样做了:

    editText.setInputType( InputType.TYPE_TEXT_VARIATION_FILTER );
    

    它隐藏了建议,但无限文本仍然存在,我仍然必须使用退格键删除不应该存在的字母。

  2. 将 InputType 设置为 textNoSuggestions|textVisiblePassword。

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

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

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

更好的解决方案?
如您所见,这两种方法实际上在没有其他问题的情况下无法正常工作。有没有其他我错过的方法。如果我想继续输入手势和建议,是否应该只使用TextWatcher?

【问题讨论】:

    标签: android android-edittext android-inputtype android-input-filter


    【解决方案1】:

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

    我在 cmets 中添加了一个示例来阐明发生了什么。

    制作这些全局变量:

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

    然后创建 TextWatcher 并将其添加到您的 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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-15
      • 2023-03-11
      • 2015-02-14
      • 2013-08-16
      • 2012-11-16
      相关资源
      最近更新 更多