Merge "Cascading popup menus: open submenu on mouse hover."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ca33b3547c
@@ -132,11 +132,6 @@ public class DropDownListView extends ListView {
|
||||
return selectedView != null && selectedView.isEnabled() || super.shouldShowSelector();
|
||||
}
|
||||
|
||||
protected void clearSelection() {
|
||||
setSelectedPositionInt(-1);
|
||||
setNextSelectedPositionInt(-1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHoverEvent(MotionEvent ev) {
|
||||
final int action = ev.getActionMasked();
|
||||
|
||||
13
core/java/android/widget/MenuItemHoverListener.java
Normal file
13
core/java/android/widget/MenuItemHoverListener.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package android.widget;
|
||||
|
||||
import com.android.internal.view.menu.MenuBuilder;
|
||||
|
||||
/**
|
||||
* An interface notified when a menu item is hovered. Useful for cases when hover should trigger
|
||||
* some behavior at a higher level, like managing the opening and closing of submenus.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface MenuItemHoverListener {
|
||||
public void onItemHovered(MenuBuilder menu, int position);
|
||||
}
|
||||
@@ -22,12 +22,12 @@ import android.content.res.Resources;
|
||||
import android.transition.Transition;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.internal.view.menu.ListMenuItemView;
|
||||
import com.android.internal.view.menu.MenuAdapter;
|
||||
import com.android.internal.view.menu.MenuBuilder;
|
||||
|
||||
/**
|
||||
* A MenuPopupWindow represents the popup window for menu.
|
||||
@@ -37,20 +37,32 @@ import com.android.internal.view.menu.MenuAdapter;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class MenuPopupWindow extends ListPopupWindow {
|
||||
public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverListener {
|
||||
private MenuItemHoverListener mHoverListener;
|
||||
|
||||
public MenuPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
|
||||
return new MenuDropDownListView(context, hijackFocus);
|
||||
MenuDropDownListView view = new MenuDropDownListView(context, hijackFocus);
|
||||
view.setHoverListener(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
public void setEnterTransition(Transition enterTransition) {
|
||||
mPopup.setEnterTransition(enterTransition);
|
||||
}
|
||||
|
||||
public void setExitTransition(Transition exitTransition) {
|
||||
mPopup.setExitTransition(exitTransition);
|
||||
}
|
||||
|
||||
public void setHoverListener(MenuItemHoverListener hoverListener) {
|
||||
mHoverListener = hoverListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this window is touch modal or if outside touches will be sent to
|
||||
* other windows behind it.
|
||||
@@ -59,10 +71,23 @@ public class MenuPopupWindow extends ListPopupWindow {
|
||||
mPopup.setTouchModal(touchModal);
|
||||
}
|
||||
|
||||
private static class MenuDropDownListView extends DropDownListView {
|
||||
@Override
|
||||
public void onItemHovered(MenuBuilder menu, int position) {
|
||||
// Forward up the chain
|
||||
if (mHoverListener != null) {
|
||||
mHoverListener.onItemHovered(menu, position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public static class MenuDropDownListView extends DropDownListView {
|
||||
final int mAdvanceKey;
|
||||
final int mRetreatKey;
|
||||
|
||||
private MenuItemHoverListener mHoverListener;
|
||||
|
||||
public MenuDropDownListView(Context context, boolean hijackFocus) {
|
||||
super(context, hijackFocus);
|
||||
|
||||
@@ -77,6 +102,15 @@ public class MenuPopupWindow extends ListPopupWindow {
|
||||
}
|
||||
}
|
||||
|
||||
public void setHoverListener(MenuItemHoverListener hoverListener) {
|
||||
mHoverListener = hoverListener;
|
||||
}
|
||||
|
||||
public void clearSelection() {
|
||||
setSelectedPositionInt(INVALID_POSITION);
|
||||
setNextSelectedPositionInt(INVALID_POSITION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
ListMenuItemView selectedItem = (ListMenuItemView) getSelectedView();
|
||||
@@ -99,6 +133,32 @@ public class MenuPopupWindow extends ListPopupWindow {
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onHoverEvent(MotionEvent ev) {
|
||||
boolean dispatchHover = false;
|
||||
final int position = pointToPosition((int) ev.getX(), (int) ev.getY());
|
||||
|
||||
final int action = ev.getActionMasked();
|
||||
if (action == MotionEvent.ACTION_HOVER_ENTER
|
||||
|| action == MotionEvent.ACTION_HOVER_MOVE) {
|
||||
if (position != INVALID_POSITION && position != mSelectedPosition) {
|
||||
final View hoveredItem = getChildAt(position - getFirstVisiblePosition());
|
||||
if (hoveredItem.isEnabled()) {
|
||||
dispatchHover = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean superVal = super.onHoverEvent(ev);
|
||||
|
||||
if (dispatchHover && mHoverListener != null) {
|
||||
mHoverListener.onItemHovered(
|
||||
((MenuAdapter) getAdapter()).getAdapterMenu(), position);
|
||||
}
|
||||
|
||||
return superVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -270,25 +270,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;
|
||||
}
|
||||
|
||||
if (!mShowCascadingMenus) {
|
||||
// Current menu will be dismissed by the normal helper, submenu will be shown in its
|
||||
// place. (If cascading menus are enabled, the cascading implementation will show the
|
||||
// submenu itself).
|
||||
new MenuPopupHelper(mContext, subMenu, mAnchor).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void onCloseSubMenu(SubMenuBuilder menu) {
|
||||
// The menu presenter will handle opening the submenu itself. Nothing to do here.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,17 +10,22 @@ import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.View.OnAttachStateChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.DropDownListView;
|
||||
import android.widget.MenuItemHoverListener;
|
||||
import android.widget.ListView;
|
||||
import android.widget.MenuPopupWindow;
|
||||
import android.widget.MenuPopupWindow.MenuDropDownListView;
|
||||
import android.widget.PopupWindow;
|
||||
import android.widget.PopupWindow.OnDismissListener;
|
||||
|
||||
@@ -32,8 +37,7 @@ import com.android.internal.util.Preconditions;
|
||||
* @hide
|
||||
*/
|
||||
final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemClickListener,
|
||||
MenuPresenter, OnKeyListener, PopupWindow.OnDismissListener,
|
||||
ViewTreeObserver.OnGlobalLayoutListener, View.OnAttachStateChangeListener{
|
||||
MenuPresenter, OnKeyListener, PopupWindow.OnDismissListener {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({HORIZ_POSITION_LEFT, HORIZ_POSITION_RIGHT})
|
||||
public @interface HorizPosition {}
|
||||
@@ -41,12 +45,133 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
private static final int HORIZ_POSITION_LEFT = 0;
|
||||
private static final int HORIZ_POSITION_RIGHT = 1;
|
||||
|
||||
private static final int SUBMENU_TIMEOUT_MS = 200;
|
||||
|
||||
private final Context mContext;
|
||||
private final int mMenuMaxWidth;
|
||||
private final int mPopupStyleAttr;
|
||||
private final int mPopupStyleRes;
|
||||
private final boolean mOverflowOnly;
|
||||
private final int mLayoutDirection;
|
||||
private final Handler mSubMenuHoverHandler;
|
||||
|
||||
private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isShowing()) {
|
||||
final View anchor = mShownAnchorView;
|
||||
if (anchor == null || !anchor.isShown()) {
|
||||
dismiss();
|
||||
} else if (isShowing()) {
|
||||
// Recompute window sizes and positions.
|
||||
for (MenuPopupWindow popup : mPopupWindows) {
|
||||
popup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final OnAttachStateChangeListener mAttachStateChangeListener =
|
||||
new OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) {
|
||||
mTreeObserver = v.getViewTreeObserver();
|
||||
}
|
||||
mTreeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
|
||||
}
|
||||
v.removeOnAttachStateChangeListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
private final MenuItemHoverListener mMenuItemHoverListener = new MenuItemHoverListener() {
|
||||
@Override
|
||||
public void onItemHovered(MenuBuilder menu, int position) {
|
||||
int menuIndex = -1;
|
||||
for (int i = 0; i < mListViews.size(); i++) {
|
||||
final MenuDropDownListView view = (MenuDropDownListView) mListViews.get(i);
|
||||
final MenuAdapter adapter = (MenuAdapter) view.getAdapter();
|
||||
|
||||
if (adapter.getAdapterMenu() == menu) {
|
||||
menuIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (menuIndex == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
final MenuDropDownListView view = (MenuDropDownListView) mListViews.get(menuIndex);
|
||||
final ListMenuItemView selectedItemView = (ListMenuItemView) view.getSelectedView();
|
||||
|
||||
if (selectedItemView != null && selectedItemView.isEnabled()
|
||||
&& selectedItemView.getItemData().hasSubMenu()) {
|
||||
// If the currently selected item corresponds to a submenu, schedule to open the
|
||||
// submenu on a timeout.
|
||||
|
||||
mSubMenuHoverHandler.removeCallbacksAndMessages(null);
|
||||
mSubMenuHoverHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Make sure the submenu item is still the one selected.
|
||||
if (view.getSelectedView() == selectedItemView
|
||||
&& selectedItemView.isEnabled()
|
||||
&& selectedItemView.getItemData().hasSubMenu()) {
|
||||
// Close any other submenus that might be open at the current or
|
||||
// a deeper level.
|
||||
int nextIndex = mListViews.indexOf(view) + 1;
|
||||
if (nextIndex < mListViews.size()) {
|
||||
MenuAdapter nextSubMenuAdapter =
|
||||
(MenuAdapter) mListViews.get(nextIndex).getAdapter();
|
||||
// Disable exit animation, to prevent overlapping fading out
|
||||
// submenus.
|
||||
mPopupWindows.get(nextIndex).setExitTransition(null);
|
||||
nextSubMenuAdapter.getAdapterMenu().close();
|
||||
}
|
||||
|
||||
// Then open the selected submenu.
|
||||
view.performItemClick(
|
||||
selectedItemView,
|
||||
view.getSelectedItemPosition(),
|
||||
view.getSelectedItemId());
|
||||
}
|
||||
}
|
||||
}, SUBMENU_TIMEOUT_MS);
|
||||
} else if (menuIndex + 1 < mListViews.size()) {
|
||||
// If the currently selected item does NOT corresponds to a submenu, check if there
|
||||
// is a submenu already open that is one level deeper. If so, schedule to close it
|
||||
// on a timeout.
|
||||
|
||||
final MenuDropDownListView nextView =
|
||||
(MenuDropDownListView) mListViews.get(menuIndex + 1);
|
||||
final MenuAdapter nextAdapter = (MenuAdapter) nextView.getAdapter();
|
||||
|
||||
view.clearSelection();
|
||||
|
||||
mSubMenuHoverHandler.removeCallbacksAndMessages(null);
|
||||
mSubMenuHoverHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Make sure the menu wasn't already closed by something else and that
|
||||
// it wasn't re-hovered by the user since this was scheduled.
|
||||
int nextMenuIndex = mListViews.indexOf(nextView);
|
||||
if (nextMenuIndex != -1 && nextView.getSelectedView() == null) {
|
||||
// Disable exit animation, to prevent overlapping fading out submenus.
|
||||
mPopupWindows.get(nextMenuIndex).setExitTransition(null);
|
||||
nextAdapter.getAdapterMenu().close();
|
||||
}
|
||||
}
|
||||
}, SUBMENU_TIMEOUT_MS);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private int mDropDownGravity = Gravity.NO_GRAVITY;
|
||||
private View mAnchorView;
|
||||
@@ -86,6 +211,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
mPopupWindows = new ArrayList<MenuPopupWindow>();
|
||||
mListViews = new ArrayList<DropDownListView>();
|
||||
mOffsets = new ArrayList<int[]>();
|
||||
mSubMenuHoverHandler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,12 +222,12 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
private MenuPopupWindow createPopupWindow() {
|
||||
MenuPopupWindow popupWindow = new MenuPopupWindow(
|
||||
mContext, null, mPopupStyleAttr, mPopupStyleRes);
|
||||
popupWindow.setHoverListener(mMenuItemHoverListener);
|
||||
popupWindow.setOnItemClickListener(this);
|
||||
popupWindow.setOnDismissListener(this);
|
||||
popupWindow.setAnchorView(mAnchorView);
|
||||
popupWindow.setDropDownGravity(mDropDownGravity);
|
||||
popupWindow.setModal(true);
|
||||
popupWindow.setTouchModal(false);
|
||||
return popupWindow;
|
||||
}
|
||||
|
||||
@@ -125,8 +251,10 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
if (mShownAnchorView != null) {
|
||||
final boolean addGlobalListener = mTreeObserver == null;
|
||||
mTreeObserver = mShownAnchorView.getViewTreeObserver(); // Refresh to latest
|
||||
if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
|
||||
mShownAnchorView.addOnAttachStateChangeListener(this);
|
||||
if (addGlobalListener) {
|
||||
mTreeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
|
||||
}
|
||||
mShownAnchorView.addOnAttachStateChangeListener(mAttachStateChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,6 +336,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
int y = 0;
|
||||
|
||||
if (addSubMenu) {
|
||||
popupWindow.setTouchModal(false);
|
||||
popupWindow.setEnterTransition(null);
|
||||
|
||||
ListView lastListView = mListViews.get(mListViews.size() - 1);
|
||||
@@ -331,7 +460,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
|
||||
if (menuIndex == -1 && menu == adapter.mAdapterMenu) {
|
||||
menuIndex = i;
|
||||
wasSelected = view.getSelectedItem() != null;
|
||||
wasSelected = view.getSelectedView() != null;
|
||||
}
|
||||
|
||||
// Once the menu has been found, remove it and all submenus beneath it from the
|
||||
@@ -365,12 +494,12 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
|
||||
if (mPopupWindows.size() == 0) {
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) mTreeObserver =
|
||||
mShownAnchorView.getViewTreeObserver();
|
||||
mTreeObserver.removeGlobalOnLayoutListener(this);
|
||||
if (mTreeObserver.isAlive()) {
|
||||
mTreeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
|
||||
}
|
||||
mTreeObserver = null;
|
||||
}
|
||||
mShownAnchorView.removeOnAttachStateChangeListener(this);
|
||||
mShownAnchorView.removeOnAttachStateChangeListener(mAttachStateChangeListener);
|
||||
// If every [sub]menu was dismissed, that means the whole thing was dismissed, so notify
|
||||
// the owner.
|
||||
mOnDismissListener.onDismiss();
|
||||
@@ -411,31 +540,4 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
|
||||
return mListViews.size() > 0 ? mListViews.get(mListViews.size() - 1) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isShowing()) {
|
||||
final View anchor = mShownAnchorView;
|
||||
if (anchor == null || !anchor.isShown()) {
|
||||
dismiss();
|
||||
} else if (isShowing()) {
|
||||
// Recompute window sizes and positions.
|
||||
for (MenuPopupWindow popup : mPopupWindows) {
|
||||
popup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver();
|
||||
mTreeObserver.removeGlobalOnLayoutListener(this);
|
||||
}
|
||||
v.removeOnAttachStateChangeListener(this);
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,10 @@ public class MenuAdapter extends BaseAdapter {
|
||||
findExpandedIndex();
|
||||
}
|
||||
|
||||
public boolean getForceShowIcon() {
|
||||
return mForceShowIcon;
|
||||
}
|
||||
|
||||
public void setForceShowIcon(boolean forceShow) {
|
||||
mForceShowIcon = forceShow;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnAttachStateChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
@@ -25,8 +27,7 @@ import com.android.internal.util.Preconditions;
|
||||
* viewport.
|
||||
*/
|
||||
final class StandardMenuPopup extends MenuPopup implements OnDismissListener, OnItemClickListener,
|
||||
MenuPresenter, OnKeyListener, ViewTreeObserver.OnGlobalLayoutListener,
|
||||
View.OnAttachStateChangeListener {
|
||||
MenuPresenter, OnKeyListener {
|
||||
|
||||
private final Context mContext;
|
||||
private final LayoutInflater mInflater;
|
||||
@@ -40,6 +41,37 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
// StandardMenuPopup.
|
||||
private final MenuPopupWindow mPopup;
|
||||
|
||||
private final OnGlobalLayoutListener mGlobalLayoutListener = new OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isShowing()) {
|
||||
final View anchor = mShownAnchorView;
|
||||
if (anchor == null || !anchor.isShown()) {
|
||||
dismiss();
|
||||
} else if (isShowing()) {
|
||||
// Recompute window size and position
|
||||
mPopup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final OnAttachStateChangeListener mAttachStateChangeListener =
|
||||
new OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver();
|
||||
mTreeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
|
||||
}
|
||||
v.removeOnAttachStateChangeListener(this);
|
||||
}
|
||||
};
|
||||
|
||||
private PopupWindow.OnDismissListener mOnDismissListener;
|
||||
|
||||
private View mAnchorView;
|
||||
@@ -50,7 +82,7 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
private ViewGroup mMeasureParent;
|
||||
|
||||
/** Whether the popup has been dismissed. Once dismissed, it cannot be opened again. */
|
||||
private boolean wasDismissed;
|
||||
private boolean mWasDismissed;
|
||||
|
||||
/** Whether the cached content width value is valid. */
|
||||
private boolean mHasContentWidth;
|
||||
@@ -97,7 +129,7 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mAnchorView == null) {
|
||||
if (mWasDismissed || mAnchorView == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -112,9 +144,9 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
final boolean addGlobalListener = mTreeObserver == null;
|
||||
mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
|
||||
if (addGlobalListener) {
|
||||
mTreeObserver.addOnGlobalLayoutListener(this);
|
||||
mTreeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
|
||||
}
|
||||
anchor.addOnAttachStateChangeListener(this);
|
||||
anchor.addOnAttachStateChangeListener(mAttachStateChangeListener);
|
||||
mPopup.setAnchorView(anchor);
|
||||
mPopup.setDropDownGravity(mDropDownGravity);
|
||||
|
||||
@@ -158,20 +190,20 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
|
||||
@Override
|
||||
public boolean isShowing() {
|
||||
return !wasDismissed && mPopup.isShowing();
|
||||
return !mWasDismissed && mPopup.isShowing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
wasDismissed = true;
|
||||
mWasDismissed = true;
|
||||
mMenu.close();
|
||||
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) mTreeObserver = mShownAnchorView.getViewTreeObserver();
|
||||
mTreeObserver.removeGlobalOnLayoutListener(this);
|
||||
mTreeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
|
||||
mTreeObserver = null;
|
||||
}
|
||||
mShownAnchorView.removeOnAttachStateChangeListener(this);
|
||||
mShownAnchorView.removeOnAttachStateChangeListener(mAttachStateChangeListener);
|
||||
mOnDismissListener.onDismiss();
|
||||
}
|
||||
|
||||
@@ -196,17 +228,7 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
|
||||
mPopupStyleRes);
|
||||
subPopup.setCallback(mPresenterCallback);
|
||||
|
||||
boolean preserveIconSpacing = false;
|
||||
final int count = subMenu.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
MenuItem childItem = subMenu.getItem(i);
|
||||
if (childItem.isVisible() && childItem.getIcon() != null) {
|
||||
preserveIconSpacing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
subPopup.setForceShowIcon(preserveIconSpacing);
|
||||
subPopup.setForceShowIcon(mAdapter.getForceShowIcon());
|
||||
|
||||
if (subPopup.tryShow()) {
|
||||
if (mPresenterCallback != null) {
|
||||
@@ -234,7 +256,6 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
return null;
|
||||
@@ -267,30 +288,4 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
|
||||
public ListView getListView() {
|
||||
return mPopup.getListView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isShowing()) {
|
||||
final View anchor = mShownAnchorView;
|
||||
if (anchor == null || !anchor.isShown()) {
|
||||
dismiss();
|
||||
} else if (isShowing()) {
|
||||
// Recompute window size and position
|
||||
mPopup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View v) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View v) {
|
||||
if (mTreeObserver != null) {
|
||||
if (!mTreeObserver.isAlive()) mTreeObserver = v.getViewTreeObserver();
|
||||
mTreeObserver.removeGlobalOnLayoutListener(this);
|
||||
}
|
||||
v.removeOnAttachStateChangeListener(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user