Clear popups on KEYCODE_ESCAPE as well as KEYCODE_BACK

On desktop devices, users expect that the Escape key will clear various
popup windows in the same way as the Back button will on mobile devices.
This adds support for Escape to places the Back button currently clears
ListPopupWindow, AutoCompleteTextView, PopupWindow, and ScrollView.

Bug: 174164194
Test: Open popups of each type on a device with a physical keyboard and
  press escape.
Change-Id: I32e65ce4317db7de043c8a050d87126b0f38acce
This commit is contained in:
Matthew Duggan
2021-07-06 16:10:01 +09:00
parent ab682f318a
commit 2d32eb61db
5 changed files with 37 additions and 33 deletions

View File

@@ -5938,36 +5938,37 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
boolean handled = false;
boolean okToSend = true;
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
okToSend = false;
break;
case KeyEvent.KEYCODE_BACK:
if (mFiltered && mPopup != null && mPopup.isShowing()) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.startTracking(event, this);
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
okToSend = false;
break;
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_ESCAPE:
if (mFiltered && mPopup != null && mPopup.isShowing()) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0) {
KeyEvent.DispatcherState state = getKeyDispatcherState();
if (state != null) {
state.startTracking(event, this);
}
handled = true;
} else if (event.getAction() == KeyEvent.ACTION_UP
&& event.isTracking() && !event.isCanceled()) {
handled = true;
mTextFilter.setText("");
}
handled = true;
} else if (event.getAction() == KeyEvent.ACTION_UP
&& event.isTracking() && !event.isCanceled()) {
handled = true;
mTextFilter.setText("");
}
}
okToSend = false;
break;
case KeyEvent.KEYCODE_SPACE:
// Only send spaces once we are filtered
okToSend = mFiltered;
break;
okToSend = false;
break;
case KeyEvent.KEYCODE_SPACE:
// Only send spaces once we are filtered
okToSend = mFiltered;
break;
}
if (okToSend) {

View File

@@ -788,8 +788,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isPopupShowing()
&& !mPopup.isDropDownAlwaysVisible()) {
if ((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ESCAPE)
&& isPopupShowing() && !mPopup.isDropDownAlwaysVisible()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {

View File

@@ -1071,7 +1071,8 @@ public class ListPopupWindow implements ShowableListMenu {
* @see #setModal(boolean)
*/
public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
if ((keyCode == KeyEvent.KEYCODE_BACK
|| keyCode == KeyEvent.KEYCODE_ESCAPE) && isShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
final View anchorView = mDropDownAnchorView;

View File

@@ -2521,7 +2521,8 @@ public class PopupWindow {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
|| event.getKeyCode() == KeyEvent.KEYCODE_ESCAPE) {
if (getKeyDispatcherState() == null) {
return super.dispatchKeyEvent(event);
}

View File

@@ -509,7 +509,8 @@ public class ScrollView extends FrameLayout {
mTempRect.setEmpty();
if (!canScroll()) {
if (isFocused() && event.getKeyCode() != KeyEvent.KEYCODE_BACK) {
if (isFocused() && event.getKeyCode() != KeyEvent.KEYCODE_BACK
&& event.getKeyCode() != KeyEvent.KEYCODE_ESCAPE) {
View currentFocused = findFocus();
if (currentFocused == this) currentFocused = null;
View nextFocused = FocusFinder.getInstance().findNextFocus(this,