null keyevent and actionid = 0 in onEditorAction() (Jelly Bean / Nexus 7)
Asked Answered
S

6

24

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 enter the KeyEvent = null and ActionId = 0 passed into the onEditorAction() method. Has anyone else encountered this? I'm thinking it might be a bug.

In the second if statement below I get a null pointer because the actionId = 0 and KeyEvent = null;

// 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;
    if (actionId == EditorInfo.IME_ACTION_SEARCH
            || event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
              .....Do some stuff();
     }
}
Suzansuzann answered 2/7, 2012 at 20:56 Comment(5)
Please use the android-edittext tag instead of edittext :)Justness
event is definitely sometimes null, going back to at least Honeycomb. Here is a sample project showing how I use onEditorAction(): github.com/commonsguy/cw-omnibus/tree/master/ActionBar/…Trix
@Trix I tried your example:Ardeb
As an example for my sing in this works for me: android:imeActionId="@integer/sing_in_action" android:imeActionLabel="@string/sign_in"Edina
for onEditorAction(TextView v, int actionId, KeyEvent event), actionId may be EditorInfo.IME_NULL, which means the enter key being pressed.Bibb
S
43

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();
    }
}
Suzansuzann answered 4/7, 2012 at 14:56 Comment(5)
for onEditorAction(TextView v, int actionId, KeyEvent event), actionId may be EditorInfo.IME_NULL, which means the enter key being pressed.Bibb
Awesome! Thanks. Out of multiple solutions on different questions, this one worked very well, even for Android M.Guimond
Actually, EditorInfo.IME_ACTION_DONE is the Enter/Done key, t least on Android 4.4.2.Jarad
onEditorAction() invokes twice by action down and up! if event is null, how to check KeyEvent.ACTION_DOWN?? @SuzansuzannAmusement
@arunrk, I don't know how this can happen, but you can use time for calculating a difference between events firing.Debbee
B
7

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.

  • KeyEvent = null, actionId = 5 = EditorInfo.IME_ACTION_NEXT
    • if return true, cursor remains in EditText, keyboard open
    • if return false, cursor moves to next focusable, keyboard open if necessary

Case 2: imeOptions, return key symbol = checkmark

<EditText
    android:singleLine="true"
    android:inputType="textUri"
    android:imeOptions="actionDone"/>

onEditorAction is called once.

  • KeyEvent = null, actionId = 6 = EditorInfo.IME_ACTION_DONE
    • if return true, cursor remains in EditText, keyboard open
    • if return false, cursor remains in EditText, keyboard closes

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

    • if return true, cursor remains in EditText, keyboard open, onEditorAction is NOT called a second time
    • if return false, onEditorAction is called a SECOND time:
  • KeyEvent = KeyEvent.ACTION_DOWN, actionId = 0

    • if return false, cursor moves to next focusable, keyboard open if necessary, onEditorAction is NOT called a third time
    • if return true, onEditorAction is called a THIRD time:
  • KeyEvent = KeyEvent.ACTION_UP, actionId = 0

    • if return true, cursor remains in EditText, keyboard open
    • if return false, cursor moves to next focusable, keyboard open if necessary

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.

Bogan answered 20/4, 2016 at 19:29 Comment(0)
G
3

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"

Gaffney answered 15/7, 2014 at 18:11 Comment(0)
B
2

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;
}
});
Bullheaded answered 30/9, 2012 at 11:5 Comment(1)
I wonder which reason this has.For me this is really annoying. The enter button represents the enter event, and this surely is one of the oldest and most important keys on each computer-like device with human interface. So, is there a reason, why it seems to be lost since Android 3.0 ? As I encountered this problem, I would like to know, what is wrong with EditorInfo.IME_ACTION_DONE ?Oversight
C
1

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.

Cholula answered 23/3, 2018 at 10:27 Comment(0)
T
0

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;
}
Trainman answered 13/3, 2020 at 14:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.