diff options
author | Romain Guy <romainguy@android.com> | 2009-06-17 16:49:17 -0700 |
---|---|---|
committer | Romain Guy <romainguy@android.com> | 2009-06-17 16:49:17 -0700 |
commit | 465dee4b4b491fdbb082218e5eb1010a416992f9 (patch) | |
tree | 0c7393d650f649132b4504344afc8c147ea966b8 /core/java/android/widget/AutoCompleteTextView.java | |
parent | de72697b771d33738c5f9d6c28087504e0796622 (diff) | |
download | frameworks_base-465dee4b4b491fdbb082218e5eb1010a416992f9.zip frameworks_base-465dee4b4b491fdbb082218e5eb1010a416992f9.tar.gz frameworks_base-465dee4b4b491fdbb082218e5eb1010a416992f9.tar.bz2 |
Fixes #1819572. Do not resurrect the list's selection when the user moved it away.
This is a workaround for a touch mode issue.
Touch mode is propagated lazily to windows. This causes problems in
the following scenario:
- Type something in the AutoCompleteTextView and get some results
- Move down with the d-pad to select an item in the list
- Move up with the d-pad until the selection disappears
- Type more text in the AutoCompleteTextView *using the soft keyboard*
and get new results; you are now in touch mode
- The selection comes back on the first item in the list, even though
the list is supposed to be in touch mode
Using the soft keyboard triggers the touch mode change but that change
is propagated to our window only after the first list layout, therefore
after the list attempts to resurrect the selection.
The trick to work around this issue is to pretend the list is in touch
mode when we know that the selection should not appear, that is when
we know the user moved the selection away from the list.
This boolean is set to true whenever we explicitely hide the list's
selection and reset to false whenver we know the user moved the
selection back to the list.
When this boolean is true, isInTouchMode() returns true, otherwise it
returns super.isInTouchMode().
Diffstat (limited to 'core/java/android/widget/AutoCompleteTextView.java')
-rw-r--r-- | core/java/android/widget/AutoCompleteTextView.java | 77 |
1 files changed, 64 insertions, 13 deletions
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 585ce3d..8f1b0ee 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -633,15 +633,19 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownList.getAdapter().getCount() - 1)) { // When the selection is at the top, we block the key // event to prevent focus from moving. - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); + clearListSelection(); mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); mPopup.update(); return true; + } else { + // WARNING: Please read the comment where mListSelectionHidden + // is declared + mDropDownList.mListSelectionHidden = false; } + consumed = mDropDownList.onKeyDown(keyCode, event); - if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" - + consumed); + if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed); + if (consumed) { // If it handled the key event, then the user is // navigating in the list, so we should put it in front. @@ -784,9 +788,12 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * it back. */ public void clearListSelection() { - if (mDropDownList != null) { - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); + final DropDownListView list = mDropDownList; + if (list != null) { + // WARNING: Please read the comment where mListSelectionHidden is declared + list.mListSelectionHidden = true; + list.hideSelector(); + list.requestLayout(); } } @@ -1079,8 +1086,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mPopup.showAsDropDown(getDropDownAnchorView(), mDropDownHorizontalOffset, mDropDownVerticalOffset); mDropDownList.setSelection(ListView.INVALID_POSITION); - mDropDownList.hideSelector(); - mDropDownList.requestFocus(); + clearListSelection(); post(mHideSelector); } } @@ -1123,6 +1129,18 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe mDropDownList.setOnItemClickListener(mDropDownItemClickListener); mDropDownList.setFocusable(true); mDropDownList.setFocusableInTouchMode(true); + mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView<?> parent, View view, + int position, long id) { + + if (position != -1) { + mDropDownList.mListSelectionHidden = false; + } + } + + public void onNothingSelected(AdapterView<?> parent) { + } + }); if (mItemSelectedListener != null) { mDropDownList.setOnItemSelectedListener(mItemSelectedListener); @@ -1246,10 +1264,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe private class ListSelectorHider implements Runnable { public void run() { - if (mDropDownList != null) { - mDropDownList.hideSelector(); - mDropDownList.requestLayout(); - } + clearListSelection(); } } @@ -1276,6 +1291,36 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe * passed to the drop down; the list only looks focused.</p> */ private static class DropDownListView extends ListView { + /* + * WARNING: This is a workaround for a touch mode issue. + * + * Touch mode is propagated lazily to windows. This causes problems in + * the following scenario: + * - Type something in the AutoCompleteTextView and get some results + * - Move down with the d-pad to select an item in the list + * - Move up with the d-pad until the selection disappears + * - Type more text in the AutoCompleteTextView *using the soft keyboard* + * and get new results; you are now in touch mode + * - The selection comes back on the first item in the list, even though + * the list is supposed to be in touch mode + * + * Using the soft keyboard triggers the touch mode change but that change + * is propagated to our window only after the first list layout, therefore + * after the list attempts to resurrect the selection. + * + * The trick to work around this issue is to pretend the list is in touch + * mode when we know that the selection should not appear, that is when + * we know the user moved the selection away from the list. + * + * This boolean is set to true whenever we explicitely hide the list's + * selection and reset to false whenver we know the user moved the + * selection back to the list. + * + * When this boolean is true, isInTouchMode() returns true, otherwise it + * returns super.isInTouchMode(). + */ + private boolean mListSelectionHidden; + /** * <p>Creates a new list view wrapper.</p> * @@ -1321,6 +1366,12 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe return mSelectionBottomPadding; } + @Override + public boolean isInTouchMode() { + // WARNING: Please read the comment where mListSelectionHidden is declared + return mListSelectionHidden || super.isInTouchMode(); + } + /** * <p>Returns the focus state in the drop down.</p> * |