Android - EditText TextWatcher 保持小写,不能保持插入符号(输入光标)位置
Android - EditText TextWatcher to keep lowercase, cannot keep caret (input cursor) position
我有一个表单,用户可以在其中在 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());
并使用 if
转义递归循环来控制插入符号的位置以到达 EditText 的末尾,但我找不到将插入符号保持在特定点的方法。例如,如果我写了“myema(il missing)@something.com 并想返回以在输入的每个字母处进行更正,插入符号位于字符串的末尾。
现在是奇怪的部分。我尝试将插入符号的位置保持在 beforeTextChanged(...)
之前或 onTextChanged(...)
中。在我输入内容的那一刻,插入符号的位置在每种情况下都会正确更改。不过,在我们进入递归调用的那一刻,插入符号的位置被报告为 0。我猜想当我实际键入时,插入符号的移动也被记录了,但是因为在递归调用中没有插入符号移动而不是 "pasting" EditText 中的文本我没有位置变化。
因此问题来了:如何保持插入符号的位置?我的想法是实际上对文本进行子字符串化。将所有内容都放入插入符号,使用 txtEmail.setSelection(temp.length());
进行更改,然后在 else 步骤中附加字符串的其余部分(目前尚未尝试)。有没有其他 (simpler/efficient) 方法可以用内置工具处理它?
提前致谢!
也许您遇到了困难。为什么不使用
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();
}
}
});
我有一个表单,用户可以在其中在 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());
并使用 if
转义递归循环来控制插入符号的位置以到达 EditText 的末尾,但我找不到将插入符号保持在特定点的方法。例如,如果我写了“myema(il missing)@something.com 并想返回以在输入的每个字母处进行更正,插入符号位于字符串的末尾。
现在是奇怪的部分。我尝试将插入符号的位置保持在 beforeTextChanged(...)
之前或 onTextChanged(...)
中。在我输入内容的那一刻,插入符号的位置在每种情况下都会正确更改。不过,在我们进入递归调用的那一刻,插入符号的位置被报告为 0。我猜想当我实际键入时,插入符号的移动也被记录了,但是因为在递归调用中没有插入符号移动而不是 "pasting" EditText 中的文本我没有位置变化。
因此问题来了:如何保持插入符号的位置?我的想法是实际上对文本进行子字符串化。将所有内容都放入插入符号,使用 txtEmail.setSelection(temp.length());
进行更改,然后在 else 步骤中附加字符串的其余部分(目前尚未尝试)。有没有其他 (simpler/efficient) 方法可以用内置工具处理它?
提前致谢!
也许您遇到了困难。为什么不使用
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();
}
}
});