Listen to ENTER key in Android

Carlos Pereira picture Carlos Pereira · Jun 28, 2012 · Viewed 30.8k times · Source

Here is my code:

public class CaptureENTER extends Activity implements OnKeyListener{

/* on create and other stuff in here*/

    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
                (keyCode == KeyEvent.KEYCODE_ENTER)) {
           Toast.makeText(LiVoiceActivity.this,
                                     "YOU CLICKED ENTER KEY",
                                     Toast.LENGTH_LONG).show();

        }       
        return false;
    }

I don't know what is going on, but when I press the ENTER key in my keyboard (I am using the Android emulator), the event is not activated.

What am I missing?

Answer

davidcesarino picture davidcesarino · Jun 28, 2012

Returning true is not the issue.

You're failing because you must set the listener to a View, not just the Activity.

edited for clarification:

The return value of the listener is not meant to be understood as a signal that the event will or will not be called. And it couldn't anyway, since the return clause is only called after your Toast is shown.

It's a signal to the system that further action is needed (return false) or that the method handled the event fully and properly (return true). That's why the documentation says in these words:

Returns

True if the listener has consumed the event, false otherwise.


There's a difference between:

  • Implementing the View.OnKeyListener interface in your Activity class.

That allows your Activity to implement the functionality provided by the interface in your class, i.e., to declare to the world that your Activity knows how to handle that kind of event.

Please pay attention to the fact that I said "declare". Just because you declared that you know how to handle a task doesn't mean people will give that task to you, nor does it mean that you can generate such tasks by yourself. It's a good metaphor for the implements keyword in my opinion. Here the Activity "asks for a task".

Metaphors aside, technically, the Activity is defining a way to handle that event, but it can't generate that kind of event by itself.

  • setting the View callbacks to your Activity implementation

Using that, a View binds to a listener (which happens to be your Activity), promising to notify it whenever the event happens.

It "contracts" with your Activity to receive an input (the user presses the ENTER key while the View is in focus) and notifies the Activity. And since the Activity previously declared that it's capable of performing that, BOTH parties can execute the contract as previously agreed (see previous item).

Metaphors aside again, technically, here the Activity is registered by the View to be notified later when the View trigger the event. The Activity declares how, but the View knows when.

Conclusion:

This is just a metaphor for interfaces (at least in this case). It may look complicated, but it's crystal clear when you think of it as a two-party agreement. If you need a better, technical, explanation, I suggest reading about interfaces.


Answer to the new comment question:

Hello David and everyone else. Really I can't set a listener to the whole Activity?

Not in that way. You need to override dispatchKeyEvent. An example:

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
    Toast.makeText(UITestsActivity.this,
               "YOU CLICKED ENTER KEY",
                Toast.LENGTH_LONG).show();
        return true;
    }
    return super.dispatchKeyEvent(e);
};