DispatchKeyEvent to listen for spacebar clicks

I am working on an Android project and I need to check when the sos space bar is pressed. I can perform a specific function.

The problem is that she worked on the emulator, but not on my device itself. I think this may be due to the fact that my emulator used a physical keyboard, not an on-screen virtual keyboard, but when testing on a real device its use of a virtual keyboard.

I'm trying to send keyevent

@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) { QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor); queryEditor.formatQueryText(); return true; } } 

I also tried keystroke

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { disconnectDatabase(); } else if (keyCode == KeyEvent.KEYCODE_DEL) { QueryEditor queryEditor = (QueryEditor)getSupportFragmentManager().findFragmentById(R.id.fragment_queryEditor); queryEditor.formatQueryText(); } return super.onKeyDown(keyCode, event); } 

None of them start, but if the back button is not pressed, but I need a space to trigger the event.

Thanks for any help you can provide.

UPDATE

Below is my code for creating a QueryEditor fragment and creating an event handler.

 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); iQueryEditor = (IQueryEditor)this; iErrorHandler = (IErrorHandler)this; txtQueryEditor = (EditText)getActivity().findViewById(R.id.query_txtQueryEditor); btnSubmitQuery = (ImageButton)getActivity().findViewById(R.id.query_btnPerformQuery); btnClearQuery = (ImageButton)getActivity().findViewById(R.id.query_btnDeleteQuery); txtQueryEditor.addTextChangedListener(new QueryTextChanged(getActivity(), txtQueryEditor, iQueryEditor)); setDatabaseUsed(); txtQueryEditor.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) || actionId == EditorInfo.IME_ACTION_DONE) { executeQuery(); return true; } else if (event.getKeyCode() == KeyEvent.KEYCODE_SPACE && event.getAction() == KeyEvent.ACTION_UP) { Toast.makeText(getActivity(), "Space Bar Pressed", Toast.LENGTH_SHORT).show(); return true; } return false; } }); btnSubmitQuery.setOnClickListener(mBtnSubmitQueryListener); btnClearQuery.setOnClickListener(mBtnDeleteQueryListener); } 

txtQueryEditor is the EditText I'm trying to get.

+5
source share
3 answers

Part of the answer is the KeyEvent API documentation:

As soft input methods can use multiple and ingenious text input methods, there is no guarantee that any keystroke on a soft keyboard will generate a key event: this is at the discretion of IME and the fact of sending such events is not recommended. You should never rely on getting KeyEvents for any key using the soft key method. In particular, the standard soft keyboard will never send any key event to any target application of Jelly Bean or later, and will send events only for some keystrokes of the delete and return to applications targeting an ice cream sandwich or earlier. Keep in mind that other software input methods can never send key events regardless of version. Consider using editor actions such as IME_ACTION_DONE if you need a specific interaction with the soft keyboard, as it gives more visibility to the user regarding how your application will respond to the press key.

Here is a comment left by a Google engineer:

The answer is pretty simple. Applications should never rely on an event key to control user input. The reason for this is because it leads to a very bad user interface.

To begin with, there are too many cases when it does not work. This is not suitable for CJK languages. This does not work correctly with gesture input or with voice input or with switching input or any new inventive input method that developers may have in the future. In fact, the only case when it works is only limited cases of the worst input experience: a legacy hardware-keyboard input method that is poorly suited to the mobile era.

This is why Android defines a rich API through which IMEs communicate with applications. This is an agnostic method and an agnostic language, and all software input methods implement it. Applications should use this API, and using EditText is the easiest way to do this (more on this below).

Please stop relying on previous key events for text entry - ALL. This is good for their support, but their demand is bad for everyone. This breaks the sequence, it blocks some languages ​​from your application, and it forces users to use a much poorer experience than they expect Android. And, as noted in comment No. 14, input methods are clearly not required to send key events at all, although some may choose to do this.

There are two easy ways to implement rich text APIs. Both will require some of them to run on Java lands. The first is just to use EditText. If your application needs to do its own rendering, you can either subclass it, if it suits you, or make it hidden until you make any changes to the text. You can also use DynamicLayout and Edits to achieve the same effect. Another possibility is to directly implement the InputConnection API, expanding BaseInputConnection, however this is a lot of work, and as a rule, should be performed only by applications that have a text edition, for example, an IDE or a word processor.

+6
source

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 from your code is that I call super.dispatchKeyEvent() for all other keys except SPACE_BAR. If dispatchKeyEvent returns true, then onKeyUp() will not be triggered. Therefore, if you just want to observe the space event, just comment out the line //return true;

It also works great if you use the onKeyUp() method. Do not use onKeyDown() , it can be called several times if the user holds his finger for 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 a similar approach. If your if statement is a true handle event and returns true. For the rest of your keys, call super.onKeyUp();

At least, but most importantly, if you have a view (for example, EditText), which owns the current focus and keyboard, is displayed for this view, then the code above will not be called at all (in Activity). If so, you need to implement the TextView.OnEditorActionListener listener and register a setOnEditorActionListener(TextView.OnEditorActionListener l) call for this view.

 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; } }); 

Alternatively, you can override this view and implement onKepUp() as described above.

Update

The hardware keyboard is working on the solution. Sorry to not check this more carefully.

From the documentation for Android

Note. When handling keyboard events with the KeyEvent class, you should expect that such keyboard events will only come from the hardware keyboard. You should never rely on getting an event key for any key using the soft key input method (on-screen keyboard).

However, I found how to overcome this problem. I based my research on the SearchView component and found that the following code would complete the task:

 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, use TextView.OnEditorActionListener .

+2
source

I tried using both dispatchkeyevents and onkeydown methods, but they did not work for softkeyboard. At least not in nexus 7. The only solution that worked was to add textwatcher to edittext. Below is the code:

 public class MainActivity extends ActionBarActivity { EditText editText1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText1 = (EditText) findViewById(R.id.editText1); editText1.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable arg0) { // TODO Auto-generated method stub } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { // TODO Auto-generated method stub } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // TODO Auto-generated method stub String lastChar = s.toString().substring(s.length() - 1); if (lastChar.equals(" ")) { Toast.makeText(MainActivity.this, "space bar pressed", Toast.LENGTH_SHORT).show(); } } }); } } 
-one
source

Source: https://habr.com/ru/post/1014436/


All Articles