7

My app has a ListView and an EditText sitting below it. For some reason, the TAB key doesn't trigger the onKeyListener. All other keys I'm handling (DEL, ENTER, DPAD_UP/DOWN/CENTER) are received just fine. I added a breakpoint in dispatchKeyEvent, again no luck receiving TAB events.

My app previously had a large TextView for displaying text and during this time, TAB events were received fine. The ListView has now replaced the TextView.

I'm completely mystified as to why the TAB event is no longer being received. This is on a stock Xoom, running ICS 4.0.4 & stock N1, with 2.3.6.

I've compared my current code against the version using a TextView and much of the code is just to handle the ListView in the place of the TextView. Apart from nextFocusLeft and nextFocusRight attributes, nothing else has changed for the EditText.

Edit: I just tried with Go Keyboard and Hacker's Keyboard and TAB is received fine. It appears this is with just some virtual keyboards

Al.
  • 2,285
  • 2
  • 22
  • 30

1 Answers1

0

I think I may see the problem. Looking at the source for ListView.java, there is a mechanism to consume key events that shift focus within a list item. Check out the comments preceding this method as well as the block of comments in the middle of the method.

/**
 * To avoid horizontal focus searches changing the selected item, we
 * manually focus search within the selected item (as applicable), and
 * prevent focus from jumping to something within another item.
 * @param direction one of {View.FOCUS_LEFT, View.FOCUS_RIGHT}
 * @return Whether this consumes the key event.
 */
private boolean handleHorizontalFocusWithinListItem(int direction) {
    if (direction != View.FOCUS_LEFT && direction != View.FOCUS_RIGHT)  {
        throw new IllegalArgumentException("direction must be one of"
                + " {View.FOCUS_LEFT, View.FOCUS_RIGHT}");
    }

    final int numChildren = getChildCount();
    if (mItemsCanFocus && numChildren > 0 && mSelectedPosition != INVALID_POSITION) {
        final View selectedView = getSelectedView();
        if (selectedView != null && selectedView.hasFocus() &&
                selectedView instanceof ViewGroup) {

            final View currentFocus = selectedView.findFocus();
            final View nextFocus = FocusFinder.getInstance().findNextFocus(
                    (ViewGroup) selectedView, currentFocus, direction);
            if (nextFocus != null) {
                // do the math to get interesting rect in next focus' coordinates
                currentFocus.getFocusedRect(mTempRect);
                offsetDescendantRectToMyCoords(currentFocus, mTempRect);
                offsetRectIntoDescendantCoords(nextFocus, mTempRect);
                if (nextFocus.requestFocus(direction, mTempRect)) {
                    return true;
                }
            }
            // we are blocking the key from being handled (by returning true)
            // if the global result is going to be some other view within this
            // list.  this is to acheive the overall goal of having
            // horizontal d-pad navigation remain in the current item.
            final View globalNextFocus = FocusFinder.getInstance().findNextFocus(
                    (ViewGroup) getRootView(), currentFocus, direction);
            if (globalNextFocus != null) {
                return isViewAncestorOf(globalNextFocus, this);
            }
        }
    }
    return false;
}

Are there multiple focusable items within a single list element? If so, this code will consume the tab key. If that is the case, then you may want to make some of the items unfocusable or consider another design option.

Chuck Krutsinger
  • 2,830
  • 4
  • 28
  • 50
  • I set up a test project to test this and unfortunately it didn't work. The edittext always has focus so it should always receive the keyevent, or at the very least, it should be caught in dispatchKeyEvent. This works fine with Hackers Keyboard but not the stock one. I've uploaded the test project here http://dl.dropbox.com/u/78755665/Test.zip Everything is set to be non-focusable in the listview – Al. May 23 '12 at 19:29
  • When I run it on my Samsung Galaxy SII Epic 4G, the soft keyboard doesn't even show a tab key. – Chuck Krutsinger May 25 '12 at 13:59
  • The emulator keyboard doesn't have a tab key either. – Chuck Krutsinger May 25 '12 at 14:04
  • Suggestion, try .setKeyListener() instead of setOnKeyListener() and listen for the key press. – Chuck Krutsinger May 25 '12 at 14:17
  • setKeyListener isn't appropriate for this if the documentation is anything to go by – Al. Jun 10 '12 at 19:35