DispatchKeyEvent to listen for Spacebar being pressed

前端 未结 3 1974
情深已故
情深已故 2020-12-20 23:58

I am working on an Android project and I need to check when the spacebar is pressed sos I can execute a certain function.

The problem is, it was working on the emul

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-21 00:22

    This implementation in your Activity should work:

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) {
            Log.d("test", "[Dispatch] Space bar pressed! " + event);
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
    

    The difference to your code is that I am calling super.dispatchKeyEvent() for all other keys than SPACE_BAR. If dispatchKeyEvent returns true onKeyUp() won't be triggered. So if you wish to just monitor space key event simply comment line //return true;

    It would also works fine if you use onKeyUp() method. Do not use onKeyDown(), it may be called few times if user holds his finger too long.

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_SPACE) {
            Log.d("test", "Space bar pressed!");
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
    

    Here I use similar approach. If your if statement is true handle event and return true. For the rest of your keys call super.onKeyUp();

    At least, but most important, if you have view(e.g. EditText) that owns current focus and keyboard is shown for that view then above code won't be called at all(in Activity). If this is the case you have to implement listener TextView.OnEditorActionListener and register for that view calling setOnEditorActionListener(TextView.OnEditorActionListener l).

    viewWithFocus.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
            if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) {
                Log.d("test", "[Editor] Space bar pressed! " + event);
                //TODO implement your action here
                return true;//remove this line if you want edit text to create space
            }
            return false;
        }
    });
    

    As alternative, you can override this view and implement onKepUp() like above.

    Update

    Above solution works for hardware keyboard. Sorry for not checking this more carefully.

    From Android Documentation

    Note: When handling keyboard events with the KeyEvent class and related APIs, you should expect that such keyboard events come only from a hardware keyboard. You should never rely on receiving key events for any key on a soft input method (an on-screen keyboard).

    However, I found how to overcome this problem. I have based my research on SearchView component and found that following code will do the job:

    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) {
            char last = s.charAt(s.length()-1);
            if (' ' == last) {
                Log.i("test", "space pressed");
            }
        }
    
        @Override
        public void afterTextChanged(Editable s) {
        }
    });
    

    For IME actions keep using TextView.OnEditorActionListener.

提交回复
热议问题