Fix bug 5300621 - Share menu disappears in gallery

ActionProviders (or action views) unfortunately had no way to report
that they had opened a sub-UI that would affect menu visibility
listeners used to hide action bars when not in use. This caused the
Gallery UI to hide its action bar when the share popup was open.

Add hidden API (to be made public later) to ActionProvider that can be
used to inform the menu system that a sub UI has opened or
closed. Account for this in menu visibility callbacks. Fix
ShareActionProvider to use this when its popup windows open and close.

Fix a regression where submenus were not properly reporting visibility
changes.

Change-Id: Ia6f45fb463ad106105c40d01f141c2e5c8b96f78
This commit is contained in:
Adam Powell
2011-09-21 17:17:01 -07:00
parent a80599f5be
commit 823f074a73
7 changed files with 90 additions and 5 deletions

View File

@ -58,6 +58,7 @@ import android.content.Context;
* @see MenuItem#getActionProvider()
*/
public abstract class ActionProvider {
private SubUiVisibilityListener mSubUiVisibilityListener;
/**
* Creates a new instance.
@ -138,4 +139,31 @@ public abstract class ActionProvider {
*/
public void onPrepareSubMenu(SubMenu subMenu) {
}
/**
* Notify the system that the visibility of an action view's sub-UI such as
* an anchored popup has changed. This will affect how other system
* visibility notifications occur.
*
* @hide Pending future API approval
*/
public void subUiVisibilityChanged(boolean isVisible) {
if (mSubUiVisibilityListener != null) {
mSubUiVisibilityListener.onSubUiVisibilityChanged(isVisible);
}
}
/**
* @hide Internal use only
*/
public void setSubUiVisibilityListener(SubUiVisibilityListener listener) {
mSubUiVisibilityListener = listener;
}
/**
* @hide Internal use only
*/
public interface SubUiVisibilityListener {
public void onSubUiVisibilityChanged(boolean isVisible);
}
}

View File

@ -16,6 +16,8 @@
package android.widget;
import com.android.internal.R;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@ -25,6 +27,7 @@ import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ActionProvider;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -32,8 +35,6 @@ import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
import com.android.internal.R;
/**
* This class is a view for choosing an activity for handling a given {@link Intent}.
* <p>
@ -104,6 +105,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
*/
private final int mListPopupMaxWidth;
/**
* The ActionProvider hosting this view, if applicable.
*/
ActionProvider mProvider;
/**
* Observer for the model data.
*/
@ -129,6 +135,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
getListPopupWindow().dismiss();
} else {
getListPopupWindow().show();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(true);
}
}
}
}
@ -259,6 +268,14 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
}
/**
* Set the provider hosting this view, if applicable.
* @hide Internal use only
*/
public void setProvider(ActionProvider provider) {
mProvider = provider;
}
/**
* Shows the popup window with activities.
*
@ -307,6 +324,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
popupWindow.setContentWidth(contentWidth);
popupWindow.show();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(true);
}
}
}
@ -525,6 +545,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// PopUpWindow.OnDismissListener#onDismiss
public void onDismiss() {
notifyOnDismissListener();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(false);
}
}
private void notifyOnDismissListener() {

View File

@ -157,6 +157,8 @@ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback {
* @hide
*/
public boolean onOpenSubMenu(MenuBuilder subMenu) {
if (subMenu == null) return false;
if (!subMenu.hasVisibleItems()) {
return true;
}

View File

@ -169,6 +169,7 @@ public class ShareActionProvider extends ActionProvider {
mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
activityChooserView.setProvider(this);
return activityChooserView;
}

View File

@ -24,6 +24,7 @@ import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseBooleanArray;
import android.view.ActionProvider;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
import android.view.View;
@ -40,7 +41,8 @@ import java.util.ArrayList;
/**
* MenuPresenter for building action menus as seen in the action bar and action modes.
*/
public class ActionMenuPresenter extends BaseMenuPresenter {
public class ActionMenuPresenter extends BaseMenuPresenter
implements ActionProvider.SubUiVisibilityListener {
private static final String TAG = "ActionMenuPresenter";
private View mOverflowButton;
@ -187,6 +189,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
public void updateMenuView(boolean cleared) {
super.updateMenuView(cleared);
if (mMenu != null) {
final ArrayList<MenuItemImpl> actionItems = mMenu.getActionItems();
final int count = actionItems.size();
for (int i = 0; i < count; i++) {
final ActionProvider provider = actionItems.get(i).getActionProvider();
if (provider != null) {
provider.setSubUiVisibilityListener(this);
}
}
}
final boolean hasOverflow = mReserveOverflow && mMenu != null &&
mMenu.getNonActionItems().size() > 0;
if (hasOverflow) {
@ -483,6 +496,16 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
}
}
@Override
public void onSubUiVisibilityChanged(boolean isVisible) {
if (isVisible) {
// Not a submenu, but treat it like one.
super.onSubMenuSelected(null);
} else {
mMenu.close(false);
}
}
private static class SavedState implements Parcelable {
public int openSubMenuId;
@ -590,7 +613,6 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
@Override
public void onDismiss() {
super.onDismiss();
mSubMenu.close();
mActionButtonPopup = null;
mOpenSubMenuId = 0;
}
@ -600,12 +622,17 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
@Override
public boolean onOpenSubMenu(MenuBuilder subMenu) {
if (subMenu == null) return false;
mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
return false;
}
@Override
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
if (menu instanceof SubMenuBuilder) {
((SubMenuBuilder) menu).getRootMenu().close(false);
}
}
}

View File

@ -187,7 +187,9 @@ public class IconMenuPresenter extends BaseMenuPresenter {
@Override
public boolean onOpenSubMenu(MenuBuilder subMenu) {
mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
if (subMenu != null) {
mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
}
return false;
}

View File

@ -3470,6 +3470,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
public boolean onOpenSubMenu(MenuBuilder subMenu) {
if (subMenu == null) return false;
// Set a simple callback for the submenu
subMenu.setCallback(this);