diff options
| author | Adam Powell <adamp@google.com> | 2010-12-01 13:09:24 -0800 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-12-01 13:09:24 -0800 |
| commit | c868b15418d377b7a4c78eb754fb858dfdcf0756 (patch) | |
| tree | fb5a929e4d3d486e1574d86e5030503208c37edf /core/java | |
| parent | fad778754cec0b0cc7723d0ecbc78fbfe9dbb763 (diff) | |
| parent | 8515ee846bd76aee86ec5ddfcc4dd1e626dd999c (diff) | |
Merge "Fix bug 3240444 - add OnMenuVisibilityListener for action bar."
Diffstat (limited to 'core/java')
9 files changed, 170 insertions, 44 deletions
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java index 7a6ad0f395bd..2f695202d5f3 100644 --- a/core/java/android/app/ActionBar.java +++ b/core/java/android/app/ActionBar.java @@ -168,13 +168,13 @@ public abstract class ActionBar { * @param adapter An adapter that will provide views both to display * the current navigation selection and populate views * within the dropdown navigation menu. - * @param callback A NavigationCallback that will receive events when the user + * @param callback A OnNavigationListener that will receive events when the user * selects a navigation item. * @deprecated See setListNavigationCallbacks. */ @Deprecated public abstract void setDropdownNavigationMode(SpinnerAdapter adapter, - NavigationCallback callback); + OnNavigationListener callback); /** * Set the adapter and navigation callback for list navigation mode. @@ -182,17 +182,17 @@ public abstract class ActionBar { * The supplied adapter will provide views for the expanded list as well as * the currently selected item. (These may be displayed differently.) * - * The supplied NavigationCallback will alert the application when the user + * The supplied OnNavigationListener will alert the application when the user * changes the current list selection. * * @param adapter An adapter that will provide views both to display * the current navigation selection and populate views * within the dropdown navigation menu. - * @param callback A NavigationCallback that will receive events when the user + * @param callback An OnNavigationListener that will receive events when the user * selects a navigation item. */ public abstract void setListNavigationCallbacks(SpinnerAdapter adapter, - NavigationCallback callback); + OnNavigationListener callback); /** * Set the action bar into dropdown navigation mode and supply an adapter that will @@ -201,7 +201,7 @@ public abstract class ActionBar { * @param adapter An adapter that will provide views both to display the current * navigation selection and populate views within the dropdown * navigation menu. - * @param callback A NavigationCallback that will receive events when the user + * @param callback A OnNavigationListener that will receive events when the user * selects a navigation item. * @param defaultSelectedPosition Position within the provided adapter that should be * selected from the outset. @@ -209,7 +209,7 @@ public abstract class ActionBar { */ @Deprecated public abstract void setDropdownNavigationMode(SpinnerAdapter adapter, - NavigationCallback callback, int defaultSelectedPosition); + OnNavigationListener callback, int defaultSelectedPosition); /** * Set the selected navigation item in list or tabbed navigation modes. @@ -532,9 +532,24 @@ public abstract class ActionBar { public abstract boolean isShowing(); /** - * Callback interface for ActionBar navigation events. + * Add a listener that will respond to menu visibility change events. + * + * @param listener The new listener to add + */ + public abstract void addOnMenuVisibilityListener(OnMenuVisibilityListener listener); + + /** + * Remove a menu visibility listener. This listener will no longer receive menu + * visibility change events. + * + * @param listener A listener to remove that was previously added + */ + public abstract void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener); + + /** + * Listener interface for ActionBar navigation events. */ - public interface NavigationCallback { + public interface OnNavigationListener { /** * This method is called whenever a navigation item in your action bar * is selected. @@ -547,6 +562,21 @@ public abstract class ActionBar { } /** + * Listener for receiving events when action bar menus are shown or hidden. + */ + public interface OnMenuVisibilityListener { + /** + * Called when an action bar menu is shown or hidden. Applications may want to use + * this to tune auto-hiding behavior for the action bar or pause/resume video playback, + * gameplay, or other activity within the main content area. + * + * @param isVisible True if an action bar menu is now visible, false if no action bar + * menus are visible. + */ + public void onMenuVisibilityChanged(boolean isVisible); + } + + /** * A tab in the action bar. * * <p>Tabs manage the hiding and showing of {@link Fragment}s. diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d69a179ce0f5..6b619fb5567d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2362,6 +2362,9 @@ public class Activity extends ContextThemeWrapper * @return The default implementation returns true. */ public boolean onMenuOpened(int featureId, Menu menu) { + if (featureId == Window.FEATURE_ACTION_BAR) { + mActionBar.dispatchMenuVisibilityChanged(true); + } return true; } @@ -2392,7 +2395,7 @@ public class Activity extends ContextThemeWrapper return true; } return mFragments.dispatchContextItemSelected(item); - + default: return false; } @@ -2417,6 +2420,10 @@ public class Activity extends ContextThemeWrapper case Window.FEATURE_CONTEXT_MENU: onContextMenuClosed(menu); break; + + case Window.FEATURE_ACTION_BAR: + mActionBar.dispatchMenuVisibilityChanged(false); + break; } } diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 64a4d7a71c50..f90fc59a33b3 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -735,6 +735,9 @@ public class Dialog implements DialogInterface, Window.Callback, * @see Activity#onMenuOpened(int, Menu) */ public boolean onMenuOpened(int featureId, Menu menu) { + if (featureId == Window.FEATURE_ACTION_BAR) { + mActionBar.dispatchMenuVisibilityChanged(true); + } return true; } @@ -749,6 +752,9 @@ public class Dialog implements DialogInterface, Window.Callback, * @see Activity#onPanelClosed(int, Menu) */ public void onPanelClosed(int featureId, Menu menu) { + if (featureId == Window.FEATURE_ACTION_BAR) { + mActionBar.dispatchMenuVisibilityChanged(false); + } } /** diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 20402a336306..447a062e4713 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -70,6 +70,10 @@ public class ActionBarImpl extends ActionBar { private ActionMode mActionMode; + private boolean mLastMenuVisibility; + private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners = + new ArrayList<OnMenuVisibilityListener>(); + private static final int CONTEXT_DISPLAY_NORMAL = 0; private static final int CONTEXT_DISPLAY_SPLIT = 1; @@ -120,6 +124,26 @@ public class ActionBarImpl extends ActionBar { CONTEXT_DISPLAY_NORMAL : CONTEXT_DISPLAY_SPLIT; } + public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.add(listener); + } + + public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { + mMenuVisibilityListeners.remove(listener); + } + + public void dispatchMenuVisibilityChanged(boolean isVisible) { + if (isVisible == mLastMenuVisibility) { + return; + } + mLastMenuVisibility = isVisible; + + final int count = mMenuVisibilityListeners.size(); + for (int i = 0; i < count; i++) { + mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible); + } + } + @Override public void setTitle(int resId) { setTitle(mContext.getString(resId)); @@ -138,11 +162,11 @@ public class ActionBarImpl extends ActionBar { mActionView.setCallback(null); } - public void setDropdownNavigationMode(SpinnerAdapter adapter, NavigationCallback callback) { + public void setDropdownNavigationMode(SpinnerAdapter adapter, OnNavigationListener callback) { setDropdownNavigationMode(adapter, callback, -1); } - public void setDropdownNavigationMode(SpinnerAdapter adapter, NavigationCallback callback, + public void setDropdownNavigationMode(SpinnerAdapter adapter, OnNavigationListener callback, int defaultSelectedPosition) { cleanupTabs(); setDisplayOptions(0, DISPLAY_SHOW_CUSTOM | DISPLAY_SHOW_TITLE); @@ -516,7 +540,7 @@ public class ActionBarImpl extends ActionBar { public void onMenuModeChange(MenuBuilder menu) { invalidate(); - mUpperContextView.showOverflowMenu(); + mUpperContextView.openOverflowMenu(); } } @@ -627,7 +651,7 @@ public class ActionBarImpl extends ActionBar { } @Override - public void setListNavigationCallbacks(SpinnerAdapter adapter, NavigationCallback callback) { + public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) { mActionView.setDropdownAdapter(adapter); mActionView.setCallback(callback); } diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java index b54daba3b96d..2d067da15af4 100644 --- a/core/java/com/android/internal/view/StandaloneActionMode.java +++ b/core/java/com/android/internal/view/StandaloneActionMode.java @@ -135,6 +135,6 @@ public class StandaloneActionMode extends ActionMode implements MenuBuilder.Call public void onMenuModeChange(MenuBuilder menu) { invalidate(); - mContextView.showOverflowMenu(); + mContextView.openOverflowMenu(); } } diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index 621defe5fb25..84067d004f23 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -59,6 +59,22 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } }; + private class OpenOverflowRunnable implements Runnable { + private MenuPopupHelper mPopup; + + public OpenOverflowRunnable(MenuPopupHelper popup) { + mPopup = popup; + } + + public void run() { + mOverflowPopup = mPopup; + mPopup.show(); + mPostedOpenRunnable = null; + } + } + + private OpenOverflowRunnable mPostedOpenRunnable; + public ActionMenuView(Context context) { this(context, null); } @@ -100,6 +116,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo @Override public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); final int screen = newConfig.screenLayout; mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE; @@ -115,6 +132,14 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } } + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mOverflowPopup != null && mOverflowPopup.isShowing()) { + mOverflowPopup.dismiss(); + } + } + private int getMaxActionButtons() { return getResources().getInteger(com.android.internal.R.integer.max_action_buttons); } @@ -193,30 +218,34 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo } public boolean showOverflowMenu() { - if (mOverflowButton != null) { - final MenuPopupHelper popup = - new MenuPopupHelper(getContext(), mMenu, mOverflowButton, true); - // Post this for later; we might still need a layout for the anchor to be right. - post(new Runnable() { - public void run() { - popup.show(); - } - }); - mOverflowPopup = popup; + if (mOverflowButton != null && !isOverflowMenuShowing()) { + mMenu.getCallback().onMenuModeChange(mMenu); return true; } return false; } + public void openOverflowMenu() { + OverflowPopup popup = new OverflowPopup(getContext(), mMenu, mOverflowButton, true); + mPostedOpenRunnable = new OpenOverflowRunnable(popup); + // Post this for later; we might still need a layout for the anchor to be right. + post(mPostedOpenRunnable); + } + public boolean isOverflowMenuShowing() { - MenuPopupHelper popup = mOverflowPopup; - if (popup != null) { - return popup.isShowing(); - } - return false; + return mOverflowPopup != null && mOverflowPopup.isShowing(); + } + + public boolean isOverflowMenuOpen() { + return mOverflowPopup != null; } public boolean hideOverflowMenu() { + if (mPostedOpenRunnable != null) { + removeCallbacks(mPostedOpenRunnable); + return true; + } + MenuPopupHelper popup = mOverflowPopup; if (popup != null) { popup.dismiss(); @@ -274,9 +303,22 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo return true; } - // Change to overflow mode - mMenu.getCallback().onMenuModeChange(mMenu); + showOverflowMenu(); return true; } } + + private class OverflowPopup extends MenuPopupHelper { + public OverflowPopup(Context context, MenuBuilder menu, View anchorView, + boolean overflowOnly) { + super(context, menu, anchorView, overflowOnly); + } + + @Override + public void onDismiss() { + super.onDismiss(); + mMenu.getCallback().onCloseMenu(mMenu, true); + mOverflowPopup = null; + } + } } diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index 1406e4e1d5c9..2cb78a58c49b 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -35,7 +35,7 @@ import java.lang.ref.WeakReference; * @hide */ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener, - ViewTreeObserver.OnGlobalLayoutListener { + ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener { private static final String TAG = "MenuPopupHelper"; private Context mContext; @@ -46,12 +46,6 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On private boolean mOverflowOnly; private ViewTreeObserver mTreeObserver; - private PopupWindow.OnDismissListener mDismissListener = new PopupWindow.OnDismissListener() { - public void onDismiss() { - mPopup = null; - } - }; - public MenuPopupHelper(Context context, MenuBuilder menu) { this(context, menu, null, false); } @@ -77,7 +71,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On public void show() { mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle); mPopup.setOnItemClickListener(this); - mPopup.setOnDismissListener(mDismissListener); + mPopup.setOnDismissListener(this); final MenuAdapter adapter = mOverflowOnly ? mMenu.getOverflowMenuAdapter(MenuBuilder.TYPE_POPUP) : @@ -110,8 +104,12 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On if (isShowing()) { mPopup.dismiss(); } + } + + public void onDismiss() { + mPopup = null; if (mTreeObserver != null) { - mTreeObserver.removeGlobalOnLayoutListener(this); + mTreeObserver.removeGlobalOnLayoutListener(MenuPopupHelper.this); mTreeObserver = null; } } diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java index e93c414fd774..cbf12bf81962 100644 --- a/core/java/com/android/internal/widget/ActionBarContextView.java +++ b/core/java/com/android/internal/widget/ActionBarContextView.java @@ -180,6 +180,12 @@ public class ActionBarContextView extends ViewGroup { return false; } + public void openOverflowMenu() { + if (mMenuView != null) { + mMenuView.openOverflowMenu(); + } + } + public boolean hideOverflowMenu() { if (mMenuView != null) { return mMenuView.hideOverflowMenu(); diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java index f931217edc45..07a65fcb94ff 100644 --- a/core/java/com/android/internal/widget/ActionBarView.java +++ b/core/java/com/android/internal/widget/ActionBarView.java @@ -22,7 +22,7 @@ import com.android.internal.view.menu.ActionMenuView; import com.android.internal.view.menu.MenuBuilder; import android.app.ActionBar; -import android.app.ActionBar.NavigationCallback; +import android.app.ActionBar.OnNavigationListener; import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -114,7 +114,7 @@ public class ActionBarView extends ViewGroup { private ActionMenuItem mLogoNavItem; private SpinnerAdapter mSpinnerAdapter; - private NavigationCallback mCallback; + private OnNavigationListener mCallback; private final AdapterView.OnItemSelectedListener mNavItemSelectedListener = new AdapterView.OnItemSelectedListener() { @@ -243,7 +243,7 @@ public class ActionBarView extends ViewGroup { return null; } - public void setCallback(NavigationCallback callback) { + public void setCallback(OnNavigationListener callback) { mCallback = callback; } @@ -269,6 +269,12 @@ public class ActionBarView extends ViewGroup { return false; } + public void openOverflowMenu() { + if (mMenuView != null) { + mMenuView.openOverflowMenu(); + } + } + public void postShowOverflowMenu() { post(new Runnable() { public void run() { @@ -291,6 +297,13 @@ public class ActionBarView extends ViewGroup { return false; } + public boolean isOverflowMenuOpen() { + if (mMenuView != null) { + return mMenuView.isOverflowMenuOpen(); + } + return false; + } + public boolean isOverflowReserved() { return mMenuView != null && mMenuView.isOverflowReserved(); } |
