Loading core/java/android/app/ActionBar.java +97 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,11 @@ import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.ViewParent; import android.view.Window; import android.widget.SpinnerAdapter; import java.lang.annotation.Retention; Loading Loading @@ -1070,6 +1072,62 @@ public abstract class ActionBar { public void setWindowTitle(CharSequence title) { } /** * Attempts to move focus to the ActionBar if it does not already contain the focus. * * @return {@code true} if focus changes or {@code false} if focus doesn't change. * @hide */ public boolean requestFocus() { return false; } /** * Common implementation for requestFocus that takes in the Toolbar and moves focus * to the contents. This makes the ViewGroups containing the toolbar allow focus while it stays * in the ActionBar and then prevents it again once it leaves. * * @param viewGroup The toolbar ViewGroup * @return {@code true} if focus changes or {@code false} if focus doesn't change. * @hide */ protected boolean requestFocus(ViewGroup viewGroup) { if (viewGroup != null && !viewGroup.hasFocus()) { final ViewGroup toolbar = viewGroup.getTouchscreenBlocksFocus() ? viewGroup : null; ViewParent parent = viewGroup.getParent(); ViewGroup container = null; while (parent != null && parent instanceof ViewGroup) { final ViewGroup vgParent = (ViewGroup) parent; if (vgParent.getTouchscreenBlocksFocus()) { container = vgParent; break; } parent = vgParent.getParent(); } if (container != null) { container.setTouchscreenBlocksFocus(false); } if (toolbar != null) { toolbar.setTouchscreenBlocksFocus(false); } viewGroup.requestFocus(); final View focused = viewGroup.findFocus(); if (focused != null) { focused.setOnFocusChangeListener(new FollowOutOfActionBar(viewGroup, container, toolbar)); } else { if (container != null) { container.setTouchscreenBlocksFocus(true); } if (toolbar != null) { toolbar.setTouchscreenBlocksFocus(true); } } return true; } return false; } /** * Listener interface for ActionBar navigation events. * Loading Loading @@ -1388,4 +1446,43 @@ public abstract class ActionBar { encoder.addProperty("gravity", gravity); } } /** * Tracks the focused View until it leaves the ActionBar, then it resets the * touchscreenBlocksFocus value. */ private static class FollowOutOfActionBar implements OnFocusChangeListener, Runnable { private final ViewGroup mFocusRoot; private final ViewGroup mContainer; private final ViewGroup mToolbar; public FollowOutOfActionBar(ViewGroup focusRoot, ViewGroup container, ViewGroup toolbar) { mContainer = container; mToolbar = toolbar; mFocusRoot = focusRoot; } @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { v.setOnFocusChangeListener(null); final View focused = mFocusRoot.findFocus(); if (focused != null) { focused.setOnFocusChangeListener(this); } else { mFocusRoot.post(this); } } } @Override public void run() { if (mContainer != null) { mContainer.setTouchscreenBlocksFocus(true); } if (mToolbar != null) { mToolbar.setTouchscreenBlocksFocus(true); } } } } core/java/android/app/Activity.java +18 −1 Original line number Diff line number Diff line Loading @@ -816,6 +816,7 @@ public class Activity extends ContextThemeWrapper SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK; private boolean mHasCurrentPermissionsRequest; private boolean mEatKeyUpEvent; /** Return the intent that started this activity. */ public Intent getIntent() { Loading Loading @@ -2827,9 +2828,25 @@ public class Activity extends ContextThemeWrapper // Let action bars open menus in response to the menu key prioritized over // the window handling it if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && final int keyCode = event.getKeyCode(); if (keyCode == KeyEvent.KEYCODE_MENU && mActionBar != null && mActionBar.onMenuKeyEvent(event)) { return true; } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { // Capture the Alt-up and send focus to the ActionBar final int action = event.getAction(); if (action == KeyEvent.ACTION_DOWN) { if (event.hasModifiers(KeyEvent.META_ALT_ON)) { final ActionBar actionBar = getActionBar(); if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) { mEatKeyUpEvent = true; return true; } } } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) { mEatKeyUpEvent = false; return true; } } Window win = getWindow(); Loading core/java/com/android/internal/app/ToolbarActionBar.java +10 −0 Original line number Diff line number Diff line Loading @@ -29,10 +29,14 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.view.WindowCallbackWrapper; import android.widget.SpinnerAdapter; import android.widget.Toolbar; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPresenter; import com.android.internal.widget.DecorToolbar; Loading Loading @@ -499,6 +503,12 @@ public class ToolbarActionBar extends ActionBar { } } /** @hide */ @Override public boolean requestFocus() { return requestFocus(mDecorToolbar.getViewGroup()); } private class ToolbarCallbackWrapper extends WindowCallbackWrapper { public ToolbarCallbackWrapper(Window.Callback wrapped) { super(wrapped); Loading core/java/com/android/internal/app/WindowDecorActionBar.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.app; import android.animation.ValueAnimator; import android.content.res.TypedArray; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.Toolbar; Loading Loading @@ -950,6 +952,12 @@ public class WindowDecorActionBar extends ActionBar implements return false; } /** @hide */ @Override public boolean requestFocus() { return requestFocus(mDecorToolbar.getViewGroup()); } /** * @hide */ Loading Loading
core/java/android/app/ActionBar.java +97 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,11 @@ import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewHierarchyEncoder; import android.view.ViewParent; import android.view.Window; import android.widget.SpinnerAdapter; import java.lang.annotation.Retention; Loading Loading @@ -1070,6 +1072,62 @@ public abstract class ActionBar { public void setWindowTitle(CharSequence title) { } /** * Attempts to move focus to the ActionBar if it does not already contain the focus. * * @return {@code true} if focus changes or {@code false} if focus doesn't change. * @hide */ public boolean requestFocus() { return false; } /** * Common implementation for requestFocus that takes in the Toolbar and moves focus * to the contents. This makes the ViewGroups containing the toolbar allow focus while it stays * in the ActionBar and then prevents it again once it leaves. * * @param viewGroup The toolbar ViewGroup * @return {@code true} if focus changes or {@code false} if focus doesn't change. * @hide */ protected boolean requestFocus(ViewGroup viewGroup) { if (viewGroup != null && !viewGroup.hasFocus()) { final ViewGroup toolbar = viewGroup.getTouchscreenBlocksFocus() ? viewGroup : null; ViewParent parent = viewGroup.getParent(); ViewGroup container = null; while (parent != null && parent instanceof ViewGroup) { final ViewGroup vgParent = (ViewGroup) parent; if (vgParent.getTouchscreenBlocksFocus()) { container = vgParent; break; } parent = vgParent.getParent(); } if (container != null) { container.setTouchscreenBlocksFocus(false); } if (toolbar != null) { toolbar.setTouchscreenBlocksFocus(false); } viewGroup.requestFocus(); final View focused = viewGroup.findFocus(); if (focused != null) { focused.setOnFocusChangeListener(new FollowOutOfActionBar(viewGroup, container, toolbar)); } else { if (container != null) { container.setTouchscreenBlocksFocus(true); } if (toolbar != null) { toolbar.setTouchscreenBlocksFocus(true); } } return true; } return false; } /** * Listener interface for ActionBar navigation events. * Loading Loading @@ -1388,4 +1446,43 @@ public abstract class ActionBar { encoder.addProperty("gravity", gravity); } } /** * Tracks the focused View until it leaves the ActionBar, then it resets the * touchscreenBlocksFocus value. */ private static class FollowOutOfActionBar implements OnFocusChangeListener, Runnable { private final ViewGroup mFocusRoot; private final ViewGroup mContainer; private final ViewGroup mToolbar; public FollowOutOfActionBar(ViewGroup focusRoot, ViewGroup container, ViewGroup toolbar) { mContainer = container; mToolbar = toolbar; mFocusRoot = focusRoot; } @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { v.setOnFocusChangeListener(null); final View focused = mFocusRoot.findFocus(); if (focused != null) { focused.setOnFocusChangeListener(this); } else { mFocusRoot.post(this); } } } @Override public void run() { if (mContainer != null) { mContainer.setTouchscreenBlocksFocus(true); } if (mToolbar != null) { mToolbar.setTouchscreenBlocksFocus(true); } } } }
core/java/android/app/Activity.java +18 −1 Original line number Diff line number Diff line Loading @@ -816,6 +816,7 @@ public class Activity extends ContextThemeWrapper SharedElementCallback mExitTransitionListener = SharedElementCallback.NULL_CALLBACK; private boolean mHasCurrentPermissionsRequest; private boolean mEatKeyUpEvent; /** Return the intent that started this activity. */ public Intent getIntent() { Loading Loading @@ -2827,9 +2828,25 @@ public class Activity extends ContextThemeWrapper // Let action bars open menus in response to the menu key prioritized over // the window handling it if (event.getKeyCode() == KeyEvent.KEYCODE_MENU && final int keyCode = event.getKeyCode(); if (keyCode == KeyEvent.KEYCODE_MENU && mActionBar != null && mActionBar.onMenuKeyEvent(event)) { return true; } else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) { // Capture the Alt-up and send focus to the ActionBar final int action = event.getAction(); if (action == KeyEvent.ACTION_DOWN) { if (event.hasModifiers(KeyEvent.META_ALT_ON)) { final ActionBar actionBar = getActionBar(); if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) { mEatKeyUpEvent = true; return true; } } } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) { mEatKeyUpEvent = false; return true; } } Window win = getWindow(); Loading
core/java/com/android/internal/app/ToolbarActionBar.java +10 −0 Original line number Diff line number Diff line Loading @@ -29,10 +29,14 @@ import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.ViewParent; import android.view.Window; import android.view.WindowCallbackWrapper; import android.widget.SpinnerAdapter; import android.widget.Toolbar; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPresenter; import com.android.internal.widget.DecorToolbar; Loading Loading @@ -499,6 +503,12 @@ public class ToolbarActionBar extends ActionBar { } } /** @hide */ @Override public boolean requestFocus() { return requestFocus(mDecorToolbar.getViewGroup()); } private class ToolbarCallbackWrapper extends WindowCallbackWrapper { public ToolbarCallbackWrapper(Window.Callback wrapped) { super(wrapped); Loading
core/java/com/android/internal/app/WindowDecorActionBar.java +8 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.app; import android.animation.ValueAnimator; import android.content.res.TypedArray; import android.view.View.OnFocusChangeListener; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.Toolbar; Loading Loading @@ -950,6 +952,12 @@ public class WindowDecorActionBar extends ActionBar implements return false; } /** @hide */ @Override public boolean requestFocus() { return requestFocus(mDecorToolbar.getViewGroup()); } /** * @hide */ Loading