Android EditText 符号必须保持在初始位置
Android EditText Symbol must remain at initial position
我有一个文本字段,其起始符号是 $(可以是欧元或英镑,具体取决于应用程序设置)。我需要这样做,以便如果用户在符号之前单击什么也不会发生。换句话说,选择必须保留在符号之后。我尝试做这样的事情,但它似乎是错误的,它给了我一个错误:
billAmount.addTextChangedListener(new TextWatcher() {
//other methods
@Override
public void afterTextChanged(Editable s) {
billAmount.setText(currencySymbol + billAmount.getText().toString());
}
});
我正在考虑使用 inputFilter,但我尝试过但没有任何效果。我也不允许在 EditText 之前使用 TextView。
我猜你得到了 WhosebugException
。
试试这个
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);
首先,在您的代码示例中,出现错误的原因是,正如其他人所说,您在 afterTextChanged
方法中调用了 setText
方法。调用 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
为零,我们知道它将被替换,在这种情况下,我们只需 return source
(表示替换文本),货币符号放在前面。否则,我们通过 returning null
.
表明更改是正确的
我测试了它,它似乎可以满足你的需要。
附带说明一下,虽然我知道您 "allowed" 不适合使用 TextView
,但我认为值得重申的是,使用 TextView
可以更好地解决此问题。一个特别有用的解决方案是隐藏 EditText
包含来自用户的原始输入,并在 EditText
之上添加 TextView
。您可以使用 TextWatcher
来更新 TextView
,并使用来自 EditText
.
的格式正确的输入
我有一个文本字段,其起始符号是 $(可以是欧元或英镑,具体取决于应用程序设置)。我需要这样做,以便如果用户在符号之前单击什么也不会发生。换句话说,选择必须保留在符号之后。我尝试做这样的事情,但它似乎是错误的,它给了我一个错误:
billAmount.addTextChangedListener(new TextWatcher() {
//other methods
@Override
public void afterTextChanged(Editable s) {
billAmount.setText(currencySymbol + billAmount.getText().toString());
}
});
我正在考虑使用 inputFilter,但我尝试过但没有任何效果。我也不允许在 EditText 之前使用 TextView。
我猜你得到了 WhosebugException
。
试试这个
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);
首先,在您的代码示例中,出现错误的原因是,正如其他人所说,您在 afterTextChanged
方法中调用了 setText
方法。调用 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
为零,我们知道它将被替换,在这种情况下,我们只需 return source
(表示替换文本),货币符号放在前面。否则,我们通过 returning null
.
我测试了它,它似乎可以满足你的需要。
附带说明一下,虽然我知道您 "allowed" 不适合使用 TextView
,但我认为值得重申的是,使用 TextView
可以更好地解决此问题。一个特别有用的解决方案是隐藏 EditText
包含来自用户的原始输入,并在 EditText
之上添加 TextView
。您可以使用 TextWatcher
来更新 TextView
,并使用来自 EditText
.