我有一个文本字段,其中起始符号为$(可能是欧元或英镑,具体取决于应用程序设置)。我需要这样做,以便如果用户在符号之前点击,则不会发生任何事情。换句话说,选择必须保留在符号之后。我尝试过这样的事情,但似乎错了,它给了我一个错误:
billAmount.addTextChangedListener(new TextWatcher() {
//other methods
@Override
public void afterTextChanged(Editable s) {
billAmount.setText(currencySymbol + billAmount.getText().toString());
}
});
我正在考虑使用inputFilter,但我没有尝试过。我也不允许在EditText之前使用TextView。
答案 0 :(得分:1)
首先,在您的代码示例中,您收到错误的原因是,正如其他人所说,您在setText
方法中调用了afterTextChanged
方法。调用setText
显然正在更改导致再次调用afterTextChanged
的文本。这会导致afterTextChanged
被连续调用,直到最终出现堆栈溢出。
您有两个问题:1)您希望始终将光标放在货币符号后面,并且2)您希望确保货币符号永远不会被移除。
解决#1的最简单方法是创建EditText
的子类并覆盖onSelectionChanged
方法。
public class MyEditText extends EditText {
// ...
@Override
public void onSelectionChanged(int selStart, int selEnd) {
super.onSelectionChanged(selStart, selEnd);
// Make sure the text's length is greater than zero.
// Then, if the cursor is at position zero...
if (getText().length() > 0 && selStart == 0) {
// ...move it over to position one.
setSelection(1, selEnd);
}
}
}
这将强制光标始终在货币符号后面,即使用户尝试在它之前移动它。检查getText().length() > 0
是为了确保EditText
包含至少一个字符,否则尝试移动光标将导致异常。
对于#2,有几种方法可以实现。您可以尝试在TextWatcher中使用一些实例变量来跟踪文本何时需要格式化,但这不会阻止实际发生不必要的方法调用,并且会增加一些不必要的复杂性。我认为简单地使用InputFilter
会更容易,您可以在扩展的EditText构造函数中指定它。
public class MyEditText extends EditText {
public MyEditText(Context context) {
super(context);
// Set the EditText's input filter.
setFilters(new InputFilter[] { new InputFilter {
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
// If the currency symbol is about to be replaced...
if (dstart == 0)
// Add the currency symbol to the front of the source.
return currencySymbol + source;
// else
// Return null to indicate that the change is okay.
return null;
}
}});
}
// ...
}
在filter
方法中,dest
参数代表EditText
的文字,dstart
和dend
参数代表开始和即将被替换的文本部分的结束位置。由于货币符号应该始终是第一个字符,我们知道如果dstart
为零,它将被替换,在这种情况下,我们只需返回source
(代表替换文本)的货币符号放在前面。否则,我们通过返回null
来表明更改是可以的。
我测试了它,它似乎适用于你需要的东西。
另一方面,虽然我明白你并没有"允许"使用TextView
,我认为值得重申的是,使用一个可以为这个问题提供更好的解决方案。一个特别有用的解决方案是让隐藏的EditText
包含来自用户的原始输入,并使TextView
位于EditText
之上。您可以使用TextWatcher
使用TextView
中格式正确的输入更新EditText
。
答案 1 :(得分:0)
我猜你得到了StackOverFlowException
。
试试这个
String oldValue="";//instace variable
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//bilamount always starts with your currency symbol
if (s != null && s.length() == 0) {
editText.setText("$");
editText.setSelection(1);
}
if (s != null && s.length() > 0) {
String billAmount = s.toString();
if (!oldValue.equals(billAmount)) {//minimize unnecessary setText() method call
oldValue= billAmount;
editText.setText(billAmount);
editText.setSelection(billAmount.length());
}
}
}
注意:您的EditText首次使用currencySymbol
初始化,即billAmount.setText(currencySymbol);