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

Commit ba630dba authored by Oren Blasberg's avatar Oren Blasberg Committed by Android (Google) Code Review
Browse files

Merge "Fix broken popup menu in Shelf (andromeda)."

parents e0fa3b46 9916282b
Loading
Loading
Loading
Loading
+53 −6
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.DropDownListView;
@@ -31,7 +32,8 @@ import com.android.internal.util.Preconditions;
 * @hide
 */
final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemClickListener,
        MenuPresenter, OnKeyListener, PopupWindow.OnDismissListener {
        MenuPresenter, OnKeyListener, PopupWindow.OnDismissListener,
        ViewTreeObserver.OnGlobalLayoutListener, View.OnAttachStateChangeListener{
    @Retention(RetentionPolicy.SOURCE)
    @IntDef({HORIZ_POSITION_LEFT, HORIZ_POSITION_RIGHT})
    public @interface HorizPosition {}
@@ -47,13 +49,15 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
    private final int mLayoutDirection;

    private int mDropDownGravity = Gravity.NO_GRAVITY;
    private View mAnchor;
    private View mAnchorView;
    private View mShownAnchorView;
    private List<DropDownListView> mListViews;
    private List<MenuPopupWindow> mPopupWindows;
    private List<int[]> mOffsets;
    private int mPreferredPosition;
    private boolean mForceShowIcon;
    private Callback mPresenterCallback;
    private ViewTreeObserver mTreeObserver;
    private PopupWindow.OnDismissListener mOnDismissListener;

    /**
@@ -64,7 +68,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
    public CascadingMenuPopup(Context context, View anchor, int popupStyleAttr,
            int popupStyleRes, boolean overflowOnly) {
        mContext = Preconditions.checkNotNull(context);
        mAnchor = Preconditions.checkNotNull(anchor);
        mAnchorView = Preconditions.checkNotNull(anchor);
        mPopupStyleAttr = popupStyleAttr;
        mPopupStyleRes = popupStyleRes;
        mOverflowOnly = overflowOnly;
@@ -94,7 +98,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
                mContext, null, mPopupStyleAttr, mPopupStyleRes);
        popupWindow.setOnItemClickListener(this);
        popupWindow.setOnDismissListener(this);
        popupWindow.setAnchorView(mAnchor);
        popupWindow.setAnchorView(mAnchorView);
        popupWindow.setDropDownGravity(mDropDownGravity);
        popupWindow.setModal(true);
        popupWindow.setTouchModal(false);
@@ -116,6 +120,14 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
            popupWindow.show();
            mListViews.add((DropDownListView) popupWindow.getListView());
        }

        mShownAnchorView = mAnchorView;
        if (mShownAnchorView != null) {
            final boolean addGlobalListener = mTreeObserver == null;
            mTreeObserver = mShownAnchorView.getViewTreeObserver(); // Refresh to latest
            if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
            mShownAnchorView.addOnAttachStateChangeListener(this);
        }
    }

    @Override
@@ -160,7 +172,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
        lastListView.getLocationOnScreen(screenLocation);

        final Rect displayFrame = new Rect();
        mAnchor.getWindowVisibleDisplayFrame(displayFrame);
        mShownAnchorView.getWindowVisibleDisplayFrame(displayFrame);

        if (mPreferredPosition == HORIZ_POSITION_RIGHT) {
            final int right = screenLocation[0] + lastListView.getWidth() + nextMenuWidth;
@@ -352,6 +364,13 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
        }

        if (mPopupWindows.size() == 0) {
            if (mTreeObserver != null) {
                if (!mTreeObserver.isAlive()) mTreeObserver =
                        mShownAnchorView.getViewTreeObserver();
                mTreeObserver.removeGlobalOnLayoutListener(this);
                mTreeObserver = null;
            }
            mShownAnchorView.removeOnAttachStateChangeListener(this);
            // If every [sub]menu was dismissed, that means the whole thing was dismissed, so notify
            // the owner.
            mOnDismissListener.onDismiss();
@@ -379,7 +398,7 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl

    @Override
    public void setAnchorView(View anchor) {
        mAnchor = anchor;
        mAnchorView = anchor;
    }

    @Override
@@ -391,4 +410,32 @@ final class CascadingMenuPopup extends MenuPopup implements AdapterView.OnItemCl
    public ListView getListView() {
        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);
    }
}
 No newline at end of file
+11 −44
Original line number Diff line number Diff line
@@ -16,10 +16,11 @@

package com.android.internal.view.menu;

import com.android.internal.view.menu.MenuPresenter.Callback;

import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.PopupWindow;

/**
@@ -27,8 +28,7 @@ import android.widget.PopupWindow;
 *
 * @hide
 */
public class MenuPopupHelper implements ViewTreeObserver.OnGlobalLayoutListener,
        PopupWindow.OnDismissListener, View.OnAttachStateChangeListener {
public class MenuPopupHelper implements PopupWindow.OnDismissListener {
    private final Context mContext;
    private final MenuBuilder mMenu;
    private final boolean mOverflowOnly;
@@ -37,9 +37,9 @@ public class MenuPopupHelper implements ViewTreeObserver.OnGlobalLayoutListener,

    private View mAnchorView;
    private MenuPopup mPopup;
    private ViewTreeObserver mTreeObserver;

    private int mDropDownGravity = Gravity.NO_GRAVITY;
    private Callback mPresenterCallback;

    public MenuPopupHelper(Context context, MenuBuilder menu) {
        this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle, 0);
@@ -114,18 +114,15 @@ public class MenuPopupHelper implements ViewTreeObserver.OnGlobalLayoutListener,
            return true;
        }

        final View anchor = mAnchorView;
        if (anchor != null) {
            final boolean addGlobalListener = mTreeObserver == null;
            mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
            if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
            anchor.addOnAttachStateChangeListener(this);
            mPopup.setAnchorView(anchor);
            mPopup.setGravity(mDropDownGravity);
        } else {
        if (mAnchorView == null) {
            return false;
        }

        mPopup = createMenuPopup();
        mPopup.setAnchorView(mAnchorView);
        mPopup.setGravity(mDropDownGravity);
        mPopup.setCallback(mPresenterCallback);

        // In order for subclasses of MenuPopupHelper to satisfy the OnDismissedListener interface,
        // we must set the listener to this outer Helper rather than to the inner MenuPopup.
        // Not to worry -- the inner MenuPopup will call our own #onDismiss method after it's done
@@ -146,45 +143,15 @@ public class MenuPopupHelper implements ViewTreeObserver.OnGlobalLayoutListener,
    @Override
    public void onDismiss() {
        mPopup = null;
        if (mTreeObserver != null) {
            if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
            mTreeObserver.removeGlobalOnLayoutListener(this);
            mTreeObserver = null;
        }
        mAnchorView.removeOnAttachStateChangeListener(this);
    }

    public boolean isShowing() {
        return mPopup != null && mPopup.isShowing();
    }

    @Override
    public void onGlobalLayout() {
        if (isShowing()) {
            final View anchor = mAnchorView;
            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);
    }

    public void setCallback(MenuPresenter.Callback cb) {
        mPresenterCallback = cb;
        mPopup.setCallback(cb);
    }
}
+61 −11
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnKeyListener;
import android.view.ViewTreeObserver;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.MenuPopupWindow;
@@ -24,7 +25,8 @@ import com.android.internal.util.Preconditions;
 * viewport.
 */
final class StandardMenuPopup extends MenuPopup implements OnDismissListener, OnItemClickListener,
        MenuPresenter, OnKeyListener {
        MenuPresenter, OnKeyListener, ViewTreeObserver.OnGlobalLayoutListener,
        View.OnAttachStateChangeListener {

    private final Context mContext;
    private final LayoutInflater mInflater;
@@ -34,15 +36,22 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
    private final int mPopupMaxWidth;
    private final int mPopupStyleAttr;
    private final int mPopupStyleRes;
    // The popup window is final in order to couple its lifecycle to the lifecycle of the
    // StandardMenuPopup.
    private final MenuPopupWindow mPopup;

    private PopupWindow.OnDismissListener mOnDismissListener;

    private View mAnchorView;
    private MenuPopupWindow mPopup;
    private View mShownAnchorView;
    private Callback mPresenterCallback;
    private ViewTreeObserver mTreeObserver;

    private ViewGroup mMeasureParent;

    /** Whether the popup has been dismissed. Once dismissed, it cannot be opened again. */
    private boolean wasDismissed;

    /** Whether the cached content width value is valid. */
    private boolean mHasContentWidth;

@@ -88,18 +97,26 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
            return true;
        }

        if (mAnchorView == null) {
            return false;
        }

        mShownAnchorView = mAnchorView;

        mPopup.setOnDismissListener(this);
        mPopup.setOnItemClickListener(this);
        mPopup.setAdapter(mAdapter);
        mPopup.setModal(true);

        final View anchor = mAnchorView;
        if (anchor != null) {
        final View anchor = mShownAnchorView;
        final boolean addGlobalListener = mTreeObserver == null;
        mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
        if (addGlobalListener) {
            mTreeObserver.addOnGlobalLayoutListener(this);
        }
        anchor.addOnAttachStateChangeListener(this);
        mPopup.setAnchorView(anchor);
        mPopup.setDropDownGravity(mDropDownGravity);
        } else {
            return false;
        }

        if (!mHasContentWidth) {
            mContentWidth = measureIndividualMenuWidth(
@@ -141,14 +158,20 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On

    @Override
    public boolean isShowing() {
        return mPopup != null && mPopup.isShowing();
        return !wasDismissed && mPopup.isShowing();
    }

    @Override
    public void onDismiss() {
        mPopup = null;
        wasDismissed = true;
        mMenu.close();

        if (mTreeObserver != null) {
            if (!mTreeObserver.isAlive()) mTreeObserver = mShownAnchorView.getViewTreeObserver();
            mTreeObserver.removeGlobalOnLayoutListener(this);
            mTreeObserver = null;
        }
        mShownAnchorView.removeOnAttachStateChangeListener(this);
        mOnDismissListener.onDismiss();
    }

@@ -170,7 +193,8 @@ final class StandardMenuPopup extends MenuPopup implements OnDismissListener, On
    public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
        if (subMenu.hasVisibleItems()) {
            MenuPopupHelper subPopup = new MenuPopupHelper(
                    mContext, subMenu, mAnchorView, mOverflowOnly, mPopupStyleAttr, mPopupStyleRes);
                    mContext, subMenu, mShownAnchorView, mOverflowOnly, mPopupStyleAttr,
                    mPopupStyleRes);
            subPopup.setCallback(mPresenterCallback);

            boolean preserveIconSpacing = false;
@@ -243,4 +267,30 @@ 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);
    }
}
 No newline at end of file