Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba3f6ac5 authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "Fix bugs around restoring submenu state after activity teardown/restore"

parents 1ea4cc64 11ed1d6c
Loading
Loading
Loading
Loading
+78 −2
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@ import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;

import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseBooleanArray;
import android.view.MenuItem;
import android.view.SoundEffectConstants;
@@ -60,6 +61,9 @@ public class ActionMenuPresenter extends BaseMenuPresenter {

    private OpenOverflowRunnable mPostedOpenRunnable;

    final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
    int mOpenSubMenuId;

    public ActionMenuPresenter() {
        super(com.android.internal.R.layout.action_menu_layout,
                com.android.internal.R.layout.action_menu_item_layout);
@@ -196,8 +200,12 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
            topSubMenu = (SubMenuBuilder) topSubMenu.getParentMenu();
        }
        View anchor = findViewForItem(topSubMenu.getItem());
        if (anchor == null) return false;
        if (anchor == null) {
            if (mOverflowButton == null) return false;
            anchor = mOverflowButton;
        }

        mOpenSubMenuId = subMenu.getItem().getItemId();
        mActionButtonPopup = new ActionButtonSubmenu(mContext, subMenu);
        mActionButtonPopup.setAnchorView(anchor);
        mActionButtonPopup.show();
@@ -426,6 +434,57 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
        super.onCloseMenu(menu, allMenusAreClosing);
    }

    @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);
            }
        }
    }

    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 Parcelable.Creator<SavedState> CREATOR
                = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

    private class OverflowMenuButton extends ImageButton implements ActionMenuChildView {
        public OverflowMenuButton(Context context) {
            super(context, null, com.android.internal.R.attr.actionOverflowButtonStyle);
@@ -460,6 +519,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
        public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
                boolean overflowOnly) {
            super(context, menu, anchorView, overflowOnly);
            setCallback(mPopupPresenterCallback);
        }

        @Override
@@ -482,6 +542,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
                // Give a reasonable anchor to nested submenus.
                setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
            }

            setCallback(mPopupPresenterCallback);
        }

        @Override
@@ -489,6 +551,20 @@ public class ActionMenuPresenter extends BaseMenuPresenter {
            super.onDismiss();
            mSubMenu.close();
            mActionButtonPopup = null;
            mOpenSubMenuId = 0;
        }
    }

    private class PopupPresenterCallback implements MenuPresenter.Callback {

        @Override
        public boolean onOpenSubMenu(MenuBuilder subMenu) {
            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
            return false;
        }

        @Override
        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
        }
    }

+10 −0
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ public abstract class BaseMenuPresenter implements MenuPresenter {

    protected MenuView mMenuView;

    private int mId;

    /**
     * Construct a new BaseMenuPresenter.
     *
@@ -200,4 +202,12 @@ public abstract class BaseMenuPresenter implements MenuPresenter {
    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
        return false;
    }

    public int getId() {
        return mId;
    }

    public void setId(int id) {
        mId = id;
    }
}
+53 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Parcelable;
import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

@@ -35,7 +36,12 @@ public class IconMenuPresenter extends BaseMenuPresenter {
    private IconMenuItemView mMoreView;
    private int mMaxItems = -1;

    int mOpenSubMenuId;
    SubMenuPresenterCallback mSubMenuPresenterCallback = new SubMenuPresenterCallback();
    MenuDialogHelper mOpenSubMenu;

    private static final String VIEWS_TAG = "android:menu:icon";
    private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";

    public IconMenuPresenter() {
        super(com.android.internal.R.layout.icon_menu_layout,
@@ -86,7 +92,11 @@ public class IconMenuPresenter extends BaseMenuPresenter {
        if (!subMenu.hasVisibleItems()) return false;

        // The window manager will give us a token.
        new MenuDialogHelper(subMenu).show(null);
        MenuDialogHelper helper = new MenuDialogHelper(subMenu);
        helper.setPresenterCallback(mSubMenuPresenterCallback);
        helper.show(null);
        mOpenSubMenu = helper;
        mOpenSubMenuId = subMenu.getItem().getItemId();
        super.onSubMenuSelected(subMenu);
        return true;
    }
@@ -137,5 +147,47 @@ public class IconMenuPresenter extends BaseMenuPresenter {
        if (viewStates != null) {
            ((View) mMenuView).restoreHierarchyState(viewStates);
        }
        int subMenuId = inState.getInt(OPEN_SUBMENU_KEY, 0);
        if (subMenuId > 0 && mMenu != null) {
            MenuItem item = mMenu.findItem(subMenuId);
            if (item != null) {
                onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
            }
        }
    }

    @Override
    public Parcelable onSaveInstanceState() {
        if (mMenuView == null) {
            return null;
        }

        Bundle state = new Bundle();
        saveHierarchyState(state);
        if (mOpenSubMenuId > 0) {
            state.putInt(OPEN_SUBMENU_KEY, mOpenSubMenuId);
        }
        return state;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        restoreHierarchyState((Bundle) state);
    }

    class SubMenuPresenterCallback implements MenuPresenter.Callback {
        @Override
        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
            mOpenSubMenuId = 0;
            mOpenSubMenu.dismiss();
            mOpenSubMenu = null;
        }

        @Override
        public boolean onOpenSubMenu(MenuBuilder subMenu) {
            mOpenSubMenuId = ((SubMenuBuilder) subMenu).getItem().getItemId();
            return false;
        }

    }
}
+27 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
    private Callback mCallback;
    private MenuAdapter mAdapter;

    private int mId;

    public static final String VIEWS_TAG = "android:menu:list";

    /**
@@ -182,6 +184,31 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
        }
    }

    public void setId(int id) {
        mId = id;
    }

    @Override
    public int getId() {
        return mId;
    }

    @Override
    public Parcelable onSaveInstanceState() {
        if (mMenuView == null) {
            return null;
        }

        Bundle state = new Bundle();
        saveHierarchyState(state);
        return state;
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        restoreHierarchyState((Bundle) state);
    }

    private class MenuAdapter extends BaseAdapter {
        public int getCount() {
            ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+55 −2
Original line number Diff line number Diff line
@@ -25,8 +25,8 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseArray;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
@@ -38,7 +38,6 @@ import android.view.View;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

@@ -49,6 +48,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class MenuBuilder implements Menu {
    private static final String LOGTAG = "MenuBuilder";

    private static final String PRESENTER_KEY = "android:menu:presenters";

    private static final int[]  sCategoryToOrder = new int[] {
        1, /* No category */
        4, /* CONTAINER */
@@ -254,6 +255,58 @@ public class MenuBuilder implements Menu {
        return result;
    }

    private void dispatchSaveInstanceState(Bundle outState) {
        if (mPresenters.isEmpty()) return;

        SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>();

        for (WeakReference<MenuPresenter> ref : mPresenters) {
            final MenuPresenter presenter = ref.get();
            if (presenter == null) {
                mPresenters.remove(ref);
            } else {
                final int id = presenter.getId();
                if (id > 0) {
                    final Parcelable state = presenter.onSaveInstanceState();
                    if (state != null) {
                        presenterStates.put(id, state);
                    }
                }
            }
        }

        outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates);
    }

    private void dispatchRestoreInstanceState(Bundle state) {
        SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY);

        if (presenterStates == null || mPresenters.isEmpty()) return;

        for (WeakReference<MenuPresenter> ref : mPresenters) {
            final MenuPresenter presenter = ref.get();
            if (presenter == null) {
                mPresenters.remove(ref);
            } else {
                final int id = presenter.getId();
                if (id > 0) {
                    Parcelable parcel = presenterStates.get(id);
                    if (parcel != null) {
                        presenter.onRestoreInstanceState(parcel);
                    }
                }
            }
        }
    }

    public void savePresenterStates(Bundle outState) {
        dispatchSaveInstanceState(outState);
    }

    public void restorePresenterStates(Bundle state) {
        dispatchRestoreInstanceState(state);
    }

    public void setCallback(Callback cb) {
        mCallback = cb;
    }
Loading