package org.aisen.wen.component.cardmenu; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.view.GravityCompat; import android.support.v7.view.menu.BaseMenuPresenter; import android.support.v7.view.menu.MenuBuilder; import android.support.v7.view.menu.MenuItemImpl; import android.support.v7.view.menu.MenuPopupHelper; import android.support.v7.view.menu.MenuView; import android.support.v7.view.menu.SubMenuBuilder; import android.view.MenuItem; import android.view.View; /** * Created by wangdan on 16/9/13. */ public class CardMenuPresenter extends BaseMenuPresenter { private OpenOverflowRunnable mPostedOpenRunnable; private OverflowPopup mOverflowPopup; private ActionButtonSubmenu mActionButtonPopup; private View anchorView; int mOpenSubMenuId; CardMenuBuilder cardMenuBuilder; private final int popupStyleAttr; /** * Construct a new BaseMenuPresenter. * * @param context Context for generating system-supplied views */ public CardMenuPresenter(Context context, View anchorView, CardMenuBuilder cardMenuBuilder, CardMenuOptions options) { super(context, options.actionMenuLayoutRes, options.actionMenuItemLayoutRes); this.anchorView = anchorView; this.cardMenuBuilder = cardMenuBuilder; this.popupStyleAttr = options.popupStyleAttr; } @Override public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { // itemView.initialize(item, 0); // // final ActionMenuView menuView = (ActionMenuView) mMenuView; // final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; // actionItemView.setItemInvoker(menuView); // if (mPopupCallback == null) { // mPopupCallback = new ActionMenuPopupCallback(); // } // actionItemView.setPopupCallback(mPopupCallback); } public boolean onSubMenuSelected(SubMenuBuilder subMenu) { if (!subMenu.hasVisibleItems()) return false; SubMenuBuilder topSubMenu = subMenu; while (topSubMenu.getParentMenu() != mMenu) { topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu(); } mOpenSubMenuId = subMenu.getItem().getItemId(); 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; } } subMenu.addMenuPresenter(this, mContext); mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu, anchorView); mActionButtonPopup.setForceShowIcon(preserveIconSpacing); mActionButtonPopup.show(); super.onSubMenuSelected(subMenu); return true; } @Override public Parcelable onSaveInstanceState() { SavedState state = new SavedState(); state.openSubMenuId = mOpenSubMenuId; return state; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState saved = (SavedState) state; if (saved.openSubMenuId > 0) { MenuItem item = mMenu.findItem(saved.openSubMenuId); if (item != null) { SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu(); onSubMenuSelected(subMenu); } } } public boolean showCardMenu() { // 暂时不判断menuView // && mMenuView != null if (!isOverflowMenuShowing() && mMenu != null && mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) { OverflowPopup popup = new OverflowPopup(mContext, mMenu, anchorView, true, popupStyleAttr); mPostedOpenRunnable = new OpenOverflowRunnable(popup); // Post this for later; we might still need a layout for the anchor to be right. // ((View) mMenuView).post(mPostedOpenRunnable); anchorView.post(mPostedOpenRunnable); // ActionMenuPresenter uses null as a callback argument here // to indicate overflow is opening. super.onSubMenuSelected(null); return true; } return false; } public boolean isOverflowMenuShowing() { return mOverflowPopup != null && mOverflowPopup.isShowing(); } /** * Hide the overflow menu if it is currently showing. * * @return true if the overflow menu was hidden, false otherwise. */ public boolean hideOverflowMenu() { if (mPostedOpenRunnable != null && mMenuView != null) { ((View) mMenuView).removeCallbacks(mPostedOpenRunnable); mPostedOpenRunnable = null; return true; } MenuPopupHelper popup = mOverflowPopup; if (popup != null) { popup.dismiss(); return true; } return false; } /** * Dismiss all popup menus - overflow and submenus. * @return true if popups were dismissed, false otherwise. (This can be because none were open.) */ public boolean dismissPopupMenus() { boolean result = hideOverflowMenu(); result |= hideSubMenus(); return result; } /** * Dismiss all submenu popups. * * @return true if popups were dismissed, false otherwise. (This can be because none were open.) */ public boolean hideSubMenus() { if (mActionButtonPopup != null) { mActionButtonPopup.dismiss(); return true; } return false; } private class ActionButtonSubmenu extends MenuPopupHelper { public ActionButtonSubmenu(Context context, SubMenuBuilder subMenu, View anchorView) { super(context, subMenu, anchorView, false, popupStyleAttr); // super(context, subMenu, cardMenuBuilder.getOptions(), anchorView, false); if (cardMenuBuilder.getOptions().dropDownGravity != -1) { setGravity(cardMenuBuilder.getOptions().dropDownGravity); } else { setGravity(GravityCompat.END); } } @Override public void onDismiss() { mActionButtonPopup = null; mOpenSubMenuId = 0; super.onDismiss(); } } private class OverflowPopup extends MenuPopupHelper { OverflowPopup(Context context, MenuBuilder menu, View anchorView, boolean overflowOnly, int popupStyleAttr) { super(context, menu, anchorView, overflowOnly, popupStyleAttr); if (cardMenuBuilder.getOptions().dropDownGravity != -1) { setGravity(cardMenuBuilder.getOptions().dropDownGravity); } else { setGravity(GravityCompat.END); } } @Override public void onDismiss() { super.onDismiss(); if (mMenu != null) { mMenu.close(); } mOverflowPopup = null; } } private class OpenOverflowRunnable implements Runnable { private OverflowPopup mPopup; public OpenOverflowRunnable(OverflowPopup popup) { mPopup = popup; } public void run() { mMenu.changeMenuMode(); // final View menuView = (View) mMenuView; final View menuView = anchorView; if (menuView != null && menuView.getWindowToken() != null && mPopup.tryShow()) { mOverflowPopup = mPopup; } mPostedOpenRunnable = null; } } @Override public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { dismissPopupMenus(); super.onCloseMenu(menu, allMenusAreClosing); } private static class SavedState implements Parcelable { public int openSubMenuId; SavedState() { } SavedState(Parcel in) { openSubMenuId = in.readInt(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(openSubMenuId); } public static final Creator<SavedState> CREATOR = new Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } }; } }