我正在制作一个购物车应用程序,随着商品的添加,动态生成行。对于每个商品行,使用EditText字段表示商品数量,以便可以修改数量。由于计算需要整数,因此我使用parseInt将从更改后的EditText中获取的文本转换为整数,并在输入错误的情况下捕获任何NumberFormatException。
当输入正确时,一切正常。当输入有误时,EditText会设置回其先前的值(按预期),但如果它下面还有另一行(动态生成的行),则焦点会转移到该较低行中的EditText。期望的行为是保持在用户想要更改的EditText中的焦点。
关于成功更改时发生的焦点问题--虚拟键盘关闭并且没有保留焦点。在那个try / catch块中,我试图隐藏键盘,但这没有帮助......它在转移到较低字段时保持打开状态。
这是一张图片,如果有助于可视化:按
那么,在处理NFE并重置该字段的值后,如何使焦点保持在用户想要编辑的字段中?
这是捕获NFE的特定代码:
当输入正确时,一切正常。当输入有误时,EditText会设置回其先前的值(按预期),但如果它下面还有另一行(动态生成的行),则焦点会转移到该较低行中的EditText。期望的行为是保持在用户想要更改的EditText中的焦点。
关于成功更改时发生的焦点问题--虚拟键盘关闭并且没有保留焦点。在那个try / catch块中,我试图隐藏键盘,但这没有帮助......它在转移到较低字段时保持打开状态。
这是一张图片,如果有助于可视化:按
ENTER
键之前和之后
我已经阅读了其他关于使用requestFocus()的帖子,我已经在这里使用它,但似乎没有任何效果--也许是因为所有这些都是动态生成的?我也看到过一些帖子说,动态生成的视图没有任何ID可以用于更具体地识别应该得到焦点的内容,但也许我没有在这种情况下理解它。那么,在处理NFE并重置该字段的值后,如何使焦点保持在用户想要编辑的字段中?
这是捕获NFE的特定代码:
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
quantityCell.setText("" + savedQuantity);
quantityCell.requestFocus();
return false;
}
以下是生成该EditText字段所需的所有代码:
// create quantity edittext and add to row
final EditText quantityView = new EditText(this);
quantityView.setLayoutParams(cellParams);
quantityView.setSingleLine();
quantityView.setPadding(5, 5, 5, 5);
quantityView.setText("" + theQuantity);
quantityView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// capture old value of quantity before changing it
EditText et = (EditText)v;
savedQuantity = Integer.parseInt(et.getText().toString());
return false;
}
});
quantityView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN)
if (keyCode == KeyEvent.KEYCODE_ENTER) {
int quantity;
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TableRow theRow = (TableRow) v.getParent();
TextView nameCell = (TextView) theRow.getChildAt(0);
String name = nameCell.getText().toString();
EditText quantityCell = (EditText) theRow.getChildAt(1);
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
quantityCell.setText("" + savedQuantity);
quantityCell.requestFocus();
return false;
}
TextView unitCell = (TextView) theRow.getChildAt(2);
double unit = Double.parseDouble(unitCell.getText().toString().substring(1));
TextView totalCell = (TextView) theRow.getChildAt(3);
double total = Double.parseDouble(totalCell.getText().toString().substring(1));
totalPrice -= total;
totalQuantity -= quantity;
cartDB.changeQuantity(name, quantity, unit);
removeAllRows();
writeOrderTable();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
return true;
}
return false;
}
});
// set length of edittext line
productRow.addView(quantityView);
编辑: 看到那个catch子句中的代码,我猜想如果所需的字段保持任何焦点,隐藏虚拟键盘的行不会起作用,因此也许我应该去掉它。它在那里的原因是我曾尝试这样做(隐藏虚拟键盘)以仅删除所有焦点,但这种方法并未奏效。下面的字段仍然抓住了焦点,键盘仍然打开。
另一个编辑: 使用计算机键盘与Genymotion虚拟设备一起使用时,物理键盘不会出现这种情况(不能使用内置AVD,我有一个AMD cpu)。当同样的模拟器设置使用虚拟键盘时,问题就出现了。
最终编辑: 我将try/catch块改为以下内容,并按预期工作。更改位于catch子句中:
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
quantity = savedQuantity;
}
在上面较大的代码块中,稍后会处理当用户输入错误数据时重置该字段的代码。我猜测之前发生的原因是我在旧代码中尝试使用setText()方法来恢复旧值。
quantityView.setInputType(InputType.TYPE_CLASS_NUMBER);
它确实限制了用户输入数字,但仍然可以提交空值并且焦点仍然移动...所以几乎是一个解决方案。 - raboyle