I have an edit text which functions as a search box in my application. In Jelly Bean on my Nexus 7 when I type something into the text box which I am listening on and hit en
Ended up adding in a null check for KeyEvent. Thanks to commonsware for pointing out this happens on 3.0+. Seems more like a workaround then a solution, but it works.
// Search field logic.
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
Log.d(TAG, "onEditorAction");
if (event != null && event.getAction() != KeyEvent.ACTION_DOWN) {
return false;
} else if (actionId == EditorInfo.IME_ACTION_SEARCH
|| event == null
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
.....Do some stuff();
}
}
You dont discover the truth, if you customize return key. You need both set imeActionLabel and imeActionId in your layout. Such as:
imeActionLabel="xxxx"
imeActionId = "6"
In your java code:
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
doSomeThing();
return true;
}
return false;
}
It will work fine.
The action id is set to 0 by default for any enter event.
From the Android documentation:
actionId int: Identifier of the action. This will be either the identifier you supplied, or EditorInfo#IME_NULL if being called due to the enter key being pressed.
So the proper way to handle enter key events would be:
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_NULL) {
// Handle return key here
return true;
}
return false;
}
I found that my "bug-like behavior" was due to imeActionLabel
complicating things. I only used it because it was mentioned in the Text Fields Guide as a way to have a custom return key label. Here are the results of my tests in Lollipop,
Case 1: default, return key symbol = closing angle bracket
<EditText
android:singleLine="true"
android:inputType="textUri"/>
onEditorAction is called once.
EditorInfo.IME_ACTION_NEXT
Case 2: imeOptions
, return key symbol = checkmark
<EditText
android:singleLine="true"
android:inputType="textUri"
android:imeOptions="actionDone"/>
onEditorAction is called once.
EditorInfo.IME_ACTION_DONE
Case 3: imeActionLabel
, return key symbol = "URdone"
<EditText
android:singleLine="true"
android:inputType="textUri"
android:imeOptions="actionDone"
android:imeActionLabel="URdone"/>
onEditorAction can be called more than once.
KeyEvent = null, actionId = 0
KeyEvent = KeyEvent.ACTION_DOWN
, actionId = 0
KeyEvent = KeyEvent.ACTION_UP
, actionId = 0
NOTES:
I'm not sure if actionId = 0 is from EditorInfo.IME_ACTION_UNSPECIFIED
or EditorInfo.IME_NULL
.
If the next focusable is non-editable, the return key symbol becomes a left pointing arrow.
You can also use setOnFocusChangeListener
to override onFocusChange
, which will be called according to the above cursor behavior.
Beside KeyEvent.ACTION_UP
we also need to capture KeyEvent.ACTION_DOWN
. Unless KeyEvent.ACTION_UP
will never be passed to EditText
so our onEditorAction
will not work.
Example:
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
final boolean isEnterEvent = event != null
&& event.getKeyCode() == KeyEvent.KEYCODE_ENTER;
final boolean isEnterUpEvent = isEnterEvent && event.getAction() == KeyEvent.ACTION_UP;
final boolean isEnterDownEvent = isEnterEvent && event.getAction() == KeyEvent.ACTION_DOWN;
if (actionId == EditorInfo.IME_ACTION_DONE || isEnterUpEvent ) {
// Do your action here
performLogin();
return true;
} else if (isEnterDownEvent) {
// Capture this event to receive ACTION_UP
return true;
} else {
// We do not care on other actions
return false;
}
}
You have to replace EditorInfo.IME_ACTION_DONE
to correct version of EditorInfo.IME_ACTION_
according to android:imeOptions="actionNext"
It might be worth noting, that you can get more than one event for the click on Enter (depending on the android version). One for the KeyDown (KeyEvent.ACTION_DOWN), one for the KeyUp (KeyEvent.ACTION_UP). When I forgot to check that I accidentally started two server calls for the same action.
searchBox.setOnEditorActionListener(new OnEditorActionListener() {
// enter key in search box triggers search
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if ((event != null && event.getAction() == KeyEvent.ACTION_UP) || event==null) {
onSearchButtonClicked();
}
return true;
}
});