如何在按下回车键时停止焦点在EditText字段之间移动

4
我正在制作一个购物车应用程序,随着商品的添加,动态生成行。对于每个商品行,使用EditText字段表示商品数量,以便可以修改数量。由于计算需要整数,因此我使用parseInt将从更改后的EditText中获取的文本转换为整数,并在输入错误的情况下捕获任何NumberFormatException。
当输入正确时,一切正常。当输入有误时,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()方法来恢复旧值。

1个回答

0

我在这里看到了一个可能的答案:http://imax-live.blogspot.hk/2012/12/prevent-enter-key-on-edittext-as-multi.html

这个想法是覆盖键盘输入,使用户无法使用“回车”键的正常功能。

顺便说一下,您可以在xml中设置android:inputType="number",以便只能将数字输入到编辑文本字段中。

class MyTextView extends EditText
{
...
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        if (keyCode==KeyEvent.KEYCODE_ENTER) 
        {
            // Just ignore the [Enter] key
            return true;
        }
        // Handle all other keys in the default way
        return super.onKeyDown(keyCode, event);
    }
}

翻译那个页面后,从我在有关使用onKeyDown陷阱的文档中所看到的来看,它在虚拟键盘上不可靠,并且大多数情况下不实现它以捕获“ENTER”键。所有这些都是没有XML属性生成的,但这是一个好主意。我添加了这一行:quantityView.setInputType(InputType.TYPE_CLASS_NUMBER);它确实限制了用户输入数字,但仍然可以提交空值并且焦点仍然移动...所以几乎是一个解决方案。 - raboyle
我将标记此问题为已解决...感谢您的帖子,@VoidExplorer,我弄清楚了发生了什么。 - raboyle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接