我正在开发一个 android 应用程序,并且我有一个 EditText,用户可以在其中输入数字。我想使用不同的货币格式(比如##、##、###)来格式化数字,并且我想即时进行,即当用户输入每个数字时(而不是按下输入时)。我四处搜索,发现了TextWatcher,我首先发现它很有前途,但结果证明它绝对是一种痛苦。我在只有软键盘的 HTC Desire 手机上调试我的代码。
现在我想在用户按下数字(0 到 9)、del(退格)键和 enter 键时获得回调。从我的测试中我发现了这些(至少在我的手机上)
1) 当用户按下 del 或 enter 键时调用 editText onKeyListener。当用户按下回车键时,一次回车会调用两次 onKey 函数(我相信这是针对 ACTION_UP 和 ACTION_DOWN 的)。当用户按下 del 时,onKey 被调用一次(仅用于 ACTION_DOWN),我不知道为什么。当用户按下我也无法理解的任何数字(0 到 9)时,永远不会调用 onKey。
2) 每当用户按下任何数字(0 到 9)键时,都会调用 TextWatchers 3 个回调函数(beforeTextChanged、onTextChanged、afterTextChanged)。所以我想通过一起使用 TextWatcher 和 onKeyListener 我可以获得我需要的所有回调。
现在我的问题是这些..
1)首先在我的 HTC 软键盘中有一个键(一个带有向下箭头的键盘符号),当我点击它时,键盘会退出而不给任何回调。我仍然无法相信 android 让用户编辑字段并在不让程序处理(保存)编辑的情况下辞职。现在我的editText显示一个值而我的对象有另一个值(我在输入时保存用户编辑,并通过使用对象中的值重置editText值来处理键盘上的回击,但我对此键盘按下键没有答案) .
2)其次,我想在用户输入新数字后格式化数字。假设我在 editText 上已经有 123 并且用户输入了 4,我希望我的 editText 显示 1,234。我在 onTextChanged() 和 afterTextChanged() 上得到了完整的数字,我可以格式化数字并在任何这些回调中将其放回 editText。我应该使用哪一个?哪个是最佳实践?
3)第三个是最关键的问题。当应用程序启动时,我将当前对象值放在 editText 中。假设我在 onResume() 上放了 123,当用户输入一个数字(比如 4)时,我希望它是 1234。但是在我的 onTextChanged 回调中,我得到的是 4123。当我再按一个键(比如 5)时,我是得到 45123。因此对于用户输入,editText 光标指向文本的结尾。但是当手动设置值时,editText 光标似乎没有更新。我相信我必须在 textWatcher 回调中做一些事情,但我不知道我应该做什么。
我在下面发布我的代码。
public class AppHome extends AppBaseActivity {
private EditText ed = null;
private NumberFormat amountFormatter = null;
private boolean isUserInput = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.app_home_screen);
ed = (EditText)findViewById(R.id.main_amount_textfield);
amountFormatter = new DecimalFormat("##,##,###");
ed.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_DOWN)
return true;
String strippedAmount = ed.getText().toString().replace(",", "");
if(keyCode == KeyEvent.KEYCODE_DEL){
//delete pressed, strip number of comas and then delete least significant digit.
strippedAmount = strippedAmount.substring(0, strippedAmount.length() - 1);
int amountNumeral = 0;
try{
amountNumeral = Integer.parseInt(strippedAmount);
} catch(NumberFormatException e){
}
myObject.amount = amountNumeral;
isUserInput = false;
setFormattedAmount(amountNumeral,ed.getId());
}else if(keyCode == KeyEvent.KEYCODE_ENTER){
//enter pressed, save edits and resign keyboard
int amountNumeral = 0;
try{
amountNumeral = Integer.parseInt(strippedAmount);
} catch(NumberFormatException e){
}
myObject.amount = amountNumeral;
isUserInput = false;
setFormattedAmount(myObject.amount,ed.getId());
//save edits
save();
//resign keyboard..
InputMethodManager in = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(AppHome.this.getCurrentFocus().getWindowToken(),InputMethodManager.HIDE_NOT_ALWAYS);
}
return true;
}
});
TextWatcher inputTextWatcher = new TextWatcher() {
public void afterTextChanged(Editable s) {
if(isUserInput == false){
//textWatcher is recursive. When editText value is changed from code textWatcher callback gets called. So this variable acts as a flag which tells whether change is user generated or not..Possibly buggy code..:(
isUserInput = true;
return;
}
String strippedAmount = ed.getText().toString().replace(",", "");
int amountNumeral = 0;
try{
amountNumeral = Integer.parseInt(strippedAmount);
} catch(NumberFormatException e){
}
isUserInput = false;
setFormattedAmount(amountNumeral,ed.getId());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after){
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
ed.addTextChangedListener(inputTextWatcher);
}//end of onCreate...
public void setFormattedAmount(Integer amount, Integer inputBoxId){
double amountValue = 0;
String textString =null;
TextView amountInputBox = (TextView) findViewById(inputBoxId);
amountValue = Double.parseDouble(Integer.toString(amount));
textString = amountFormatter.format(amountValue).toString();
amountInputBox.setText(textString);
}
}
我知道这是一个大问题,但我正在处理同样的问题 2 天。我是 android 新手,仍然无法相信没有简单的方法可以即时处理 textEdit 数据(我在 iphone 上轻松地做了同样的事情)。谢谢大家
编辑:使用输入过滤器后
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String strippedAmount = dest.toString() + source;
strippedAmount = strippedAmount.replace(",", "");
int amountNumeral = 0;
try{
amountNumeral = Integer.parseInt(strippedAmount);
} catch(NumberFormatException e){
}
return amountFormatter.format(amountNumeral).toString();
}
};
ed.setFilters(new InputFilter[]{filter});
当应用程序启动时,我在 editText 上放置了 1,234
myObject.amount = 1234;
ed.setText(amountFormatter.format(myObject.amount).toString());
然后当用户单击editText时,键盘弹出,并说用户输入数字6
我得到:61234 我想要:12346