Android - EditText TextWatcher保持小写,不能保持插入符号(输入游标)的位置

时间:2017-04-20 10:56:55

标签: android recursion android-edittext caret android-textwatcher

我有一个表单,用户可以在EditText字段中输入一些数据。其中一个EditText小部件用于电子邮件地址。我正在使用TextWatcher来确保文本始终为小写,如下所示:

txtEmail.addTextChangedListener(new TextWatcher()
    {
        String prevString = "";
        boolean delAction = false;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after)
        {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            if (s.length() < prevString.length())
                delAction = true;
            else
                delAction = false;
        }

        @Override
        public void afterTextChanged(Editable s)
        {
            if (!delAction)
            {
                String temp = s.toString().toLowerCase();
                if (!temp.equals(prevString))
                {
                    prevString = temp;
                    txtEmail.setText(temp); // Recursive
                    txtEmail.setSelection(temp.length());
                }
            }
            else
            {
                prevString = s.toString();
            }
        }
    });

onTextChanged(...)我也在进行比较,以确保删除工作正常。

现在问题。 txtEmail.setText(temp);导致整个Watcher以递归方式运行。我可以通过添加txtEmail.setSelection(temp.length());来控制插入位置以转到EditText的末尾,并使用if转义递归循环,但是我找不到一种方法来保持我的插入符号在特定点。例如,如果我写了&#34; myema(il missing)@ something.com,并希望返回对每个输入的字母进行修正,则插入符号位于字符串的末尾。

现在奇怪的部分。我尝试在beforeTextChanged(...)onTextChanged(...)之前保留插入符号的位置。在我输入内容的那一刻,插入位置在每种情况下都被正确改变。然而,那一刻,我们进入递归调用,插入符号的位置报告为0.我猜测当我实际键入时,插入符号移动也被注册,但因为在递归调用中没有插入符号移动而不是&# 34;粘贴&#34;在EditText中我没有得到任何位置变化。

因此问题是:我如何保持插入符号的位置?我的想法是实际上字符串文本。获取插入符号的所有内容,然后使用txtEmail.setSelection(temp.length());将更改添加到其中,然后在else步骤中附加其余字符串(尚未尝试)。有没有其他(更简单/更有效)的方法,我可以使用内置工具处理它?<​​/ p>

提前致谢!

1 个答案:

答案 0 :(得分:1)

也许你已经采取了艰难的方式。为什么不使用

android:digits="qwertyuiopasdfghjklzxcvbnm_,.@.," 

用于电子邮件的EditText?如果您允许用户输入任何其他字符,只需将其添加到 android:digits 字段。

编辑OP:

在遵循Alexandru的建议(请参阅注释)以取消注册并再次注册TextWatcher后,代码更改并按以下方式工作:

    txtEmail.addTextChangedListener(new TextWatcher()
    {
        String prevString = "";
        boolean delAction = false;
        int caretPos = 0;

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after)
        {
            caretPos = txtEmail.getSelectionStart();
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count)
        {
            if (s.length() < prevString.length())
                delAction = true;
            else
                delAction = false;
        }

        @Override
        public void afterTextChanged(Editable s)
        {
            if (!delAction)
            {
                prevString = s.toString().toLowerCase();
                txtEmail.removeTextChangedListener(this);
                txtEmail.setText(prevString);
                txtEmail.addTextChangedListener(this);
                txtEmail.setSelection(caretPos + 1);
            }
            else
            {
                txtEmail.setSelection(caretPos - 1);
                prevString = s.toString();
            }
        }
    });