Android:有什么方法可以识别 edittext 软键盘上的键何时为 pressed/unpressed?

Android: Is there any way to identify when the keys are pressed/unpressed on an edittext softkeyboard?

我有一个自动完成的 edittext 字段,每次文本更改时都会向服务器发送查询,但是如果用户键入大量文本然后按住 "delete" 我不想发送查询每个字符都删除了。解决这个问题的一种方法是在输入字符时缓存所有查询,然后在删除时回放缓存 - 但在我看来这太复杂了。一种更简单的方法是检测 keydown/keyup ,然后仅在文本已更改但用户也没有触摸键盘时才发送查询。这让我遇到了如何从软键盘捕捉键盘的困难。

我已经尝试过 ontouchlistener(不触发)和 onkeypressedlistener(也不触发),甚至在 edittext 中覆盖 onKeyPreIme(也不触发)。有办法吗?

我解决这个问题的方法是为查询添加延迟,这样它就不会每次都执行。我的代码看起来像这样:

long lastPress = 0l;
@Override
public void onTextChanged(CharSequence s,
         int start, int before, int count){
    if(System.currentTimeMillis() - lastpress > 500){
        lastPress= System.currentTimeMillis();
        // insert query here
    }
}

希望对您有所帮助。

您无法直接检测到它,但您可以通过覆盖 Activity 中的 onMeasure 并检测它何时收缩和扩展超过某个阈值来找到间接方法,只要您在将 android:windowSoftInputMode 显示为 adjustResize

不过,根据我的经验,该方法并不是非常可靠。您还应该考虑到用户可能会在不关闭键盘的情况下离开您的 activity。

这取决于您在删除时需要采取什么样的操作,但我遇到过类似的情况,我需要将编辑后的文本保存到共享首选项中。我发现最好的解决方案是在每次删除字符时保存它:这是我发现的唯一安全且一致的方法,而且性能影响并不明显。

更好用TextWatcher

1)创建一个TextWatcher监听器对象:

 private static long time = 0;
 private final  long TIME_DELAY = 700;

 private final TextWatcher myTextWatcher = new TextWatcher() {
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        public void afterTextChanged(Editable s) {
          if(System.currentTimeMillis() - time > TIME_DELAY ){
            time= System.currentTimeMillis();
           // your codes 
           } 

        }
    };

2)将此侦听器注册到您的 edittext

myEditText.addTextChangedListener(myTextWatcher);

如果您只想识别在软键盘中按下的删除键,那么试试这个..

final EditText edit1 = (EditText) findViewById(R.id.editText1); 
edit1.setOnKeyListener(new View.OnKeyListener() { 
    @Override 
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        // You can identify which key pressed buy checking keyCode value 
        // with KeyEvent.KEYCODE_ 
        if (keyCode == KeyEvent.KEYCODE_DEL) {
            // this is for backspace 
            Log.e("IME_TEST", "DEL KEY");
        } 
        return false; 
    } 
}); 

我的最终解决方案是将 Andrea 的回答与 Jelle 的回答结合起来。我记录了最后一次在 textwatcher 中按下一个键,然后仅在 500 毫秒之后对其进行测试 - 为了确定它是最后按下的键:

private static long lastCharacterPress = 0l;
private Editable stringToSearchFor;
private Handler delayedCharacterCheck;

    edittext.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {

            lastCharacterPress = System.currentTimeMillis();
            stringToSearchFor = s;

            if (s.length() > 2) {

                delayedCharacterCheck.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        checkIfTimeHasPassed();
                    }
                }, 500);

            } else ...

        }
    });

然后我输入这个方法:

private void checkIfTimeHasPassed() {
        if (!TextUtils.isEmpty(stringToSearchFor) && edittext.getText().length() > 2 && System.currentTimeMillis() - lastCharacterPress > 499) {
                // perform the actual query
        }
    }