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

Commit 7487f905 authored by Alan Viverette's avatar Alan Viverette Committed by Android (Google) Code Review
Browse files

Merge "Animate context popup menu around origin point"

parents 11cbea90 91098574
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ public class ListPopupWindow implements ShowableListMenu {
    private int mDropDownVerticalOffset;
    private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
    private boolean mDropDownVerticalOffsetSet;
    private boolean mIsAnimatedFromAnchor = true;

    private int mDropDownGravity = Gravity.NO_GRAVITY;

@@ -101,7 +102,13 @@ public class ListPopupWindow implements ShowableListMenu {

    private final Handler mHandler;

    private Rect mTempRect = new Rect();
    private final Rect mTempRect = new Rect();

    /**
     * Optional anchor-relative bounds to be used as the transition epicenter.
     * When {@code null}, the anchor bounds are used as the epicenter.
     */
    private Rect mEpicenterBounds;

    private boolean mModal;

@@ -451,6 +458,17 @@ public class ListPopupWindow implements ShowableListMenu {
        mDropDownVerticalOffsetSet = true;
    }

    /**
     * Specifies the anchor-relative bounds of the popup's transition
     * epicenter.
     *
     * @param bounds anchor-relative bounds
     * @hide
     */
    public void setEpicenterBounds(Rect bounds) {
        mEpicenterBounds = bounds;
    }

    /**
     * Set the gravity of the dropdown list. This is commonly used to
     * set gravity to START or END for alignment with the anchor.
@@ -649,6 +667,7 @@ public class ListPopupWindow implements ShowableListMenu {
            // only set this if the dropdown is not always visible
            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
            mPopup.setTouchInterceptor(mTouchInterceptor);
            mPopup.setEpicenterBounds(mEpicenterBounds);
            mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
                    mDropDownVerticalOffset, mDropDownGravity);
            mDropDownList.setSelection(ListView.INVALID_POSITION);
+42 −3
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ public class PopupWindow {

    private Transition mEnterTransition;
    private Transition mExitTransition;
    private Rect mEpicenterBounds;

    private boolean mAboveAnchor;
    private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
@@ -345,6 +346,25 @@ public class PopupWindow {
        mExitTransition = exitTransition;
    }

    /**
     * Sets the bounds used as the epicenter of the enter and exit transitions.
     * <p>
     * Transitions use a point or Rect, referred to as the epicenter, to orient
     * the direction of travel. For popup windows, the anchor view bounds are
     * used as the default epicenter.
     * <p>
     * See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
     * information about how transition epicenters.
     *
     * @param bounds the epicenter bounds relative to the anchor view, or
     *               {@code null} to use the default epicenter
     * @see #getTransitionEpicenter()
     * @hide
     */
    public void setEpicenterBounds(Rect bounds) {
        mEpicenterBounds = bounds;
    }

    private Transition getTransition(int resId) {
        if (resId != 0 && resId != R.transition.no_transition) {
            final TransitionInflater inflater = TransitionInflater.from(mContext);
@@ -1621,7 +1641,7 @@ public class PopupWindow {
            p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
            mWindowManager.updateViewLayout(decorView, p);

            final Rect epicenter = getRelativeAnchorBounds();
            final Rect epicenter = getTransitionEpicenter();
            exitTransition.setEpicenterCallback(new EpicenterCallback() {
                @Override
                public Rect onGetEpicenter(Transition transition) {
@@ -1646,7 +1666,17 @@ public class PopupWindow {
        }
    }

    private Rect getRelativeAnchorBounds() {
    /**
     * Returns the window-relative epicenter bounds to be used by enter and
     * exit transitions.
     * <p>
     * <strong>Note:</strong> This is distinct from the rect passed to
     * {@link #setEpicenterBounds(Rect)}, which is anchor-relative.
     *
     * @return the window-relative epicenter bounds to be used by enter and
     *         exit transitions
     */
    private Rect getTransitionEpicenter() {
        final View anchor = mAnchor != null ? mAnchor.get() : null;
        final View decor = mDecorView;
        if (anchor == null || decor == null) {
@@ -1659,6 +1689,15 @@ public class PopupWindow {
        // Compute the position of the anchor relative to the popup.
        final Rect bounds = new Rect(0, 0, anchor.getWidth(), anchor.getHeight());
        bounds.offset(anchorLocation[0] - popupLocation[0], anchorLocation[1] - popupLocation[1]);

        // Use anchor-relative epicenter, if specified.
        if (mEpicenterBounds != null) {
            final int offsetX = bounds.left;
            final int offsetY = bounds.top;
            bounds.set(mEpicenterBounds);
            bounds.offset(offsetX, offsetY);
        }

        return bounds;
    }

@@ -2031,7 +2070,7 @@ public class PopupWindow {
                            observer.removeOnGlobalLayoutListener(this);
                        }

                        final Rect epicenter = getRelativeAnchorBounds();
                        final Rect epicenter = getTransitionEpicenter();
                        enterTransition.setEpicenterCallback(new EpicenterCallback() {
                            @Override
                            public Rect onGetEpicenter(Transition transition) {
+4 −0
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey

        final int x;
        final int y;
        final Rect epicenterBounds;
        if (parentView != null) {
            // This menu is a cascading submenu anchored to a parent view.
            popupWindow.setTouchModal(false);
@@ -396,13 +397,16 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey
            }

            y = parentOffsetTop;
            epicenterBounds = null;
        } else {
            x = mInitXOffset;
            y = mInitYOffset;
            epicenterBounds = getEpicenterBounds();
        }

        popupWindow.setHorizontalOffset(x);
        popupWindow.setVerticalOffset(y);
        popupWindow.setEpicenterBounds(epicenterBounds);

        final CascadingMenuInfo menuInfo = new CascadingMenuInfo(popupWindow, menu, mLastPosition);
        mShowingMenus.add(menuInfo);
+19 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.internal.view.menu;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
@@ -37,6 +38,7 @@ import android.widget.PopupWindow;
 */
public abstract class MenuPopup implements ShowableListMenu, MenuPresenter,
        AdapterView.OnItemClickListener {
    private Rect mEpicenterBounds;

    public abstract void setForceShowIcon(boolean forceShow);

@@ -59,6 +61,23 @@ public abstract class MenuPopup implements ShowableListMenu, MenuPresenter,

    public abstract void setVerticalOffset(int y);

    /**
     * Specifies the anchor-relative bounds of the popup's transition
     * epicenter.
     *
     * @param bounds anchor-relative bounds
     */
    public void setEpicenterBounds(Rect bounds) {
        mEpicenterBounds = bounds;
    }

    /**
     * @return anchor-relative bounds of the popup's transition epicenter
     */
    public Rect getEpicenterBounds() {
        return mEpicenterBounds;
    }

    /**
     * Set whether a title entry should be shown in the popup menu (if a title exists for the
     * menu).
+27 −6
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.content.Context;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.widget.PopupWindow.OnDismissListener;
@@ -31,6 +33,8 @@ import android.widget.PopupWindow.OnDismissListener;
 * Presents a menu as a small, simple popup anchored to another view.
 */
public class MenuPopupHelper implements MenuHelper {
    private static final int TOUCH_EPICENTER_SIZE_DP = 48;

    private final Context mContext;

    // Immutable cached popup menu properties.
@@ -163,6 +167,11 @@ public class MenuPopupHelper implements MenuHelper {
     * Shows the popup menu and makes a best-effort to anchor it to the
     * specified (x,y) coordinate relative to the anchor view.
     * <p>
     * Additionally, the popup's transition epicenter (see
     * {@link android.widget.PopupWindow#setEpicenterBounds(Rect)} will be
     * centered on the specified coordinate, rather than using the bounds of
     * the anchor view.
     * <p>
     * If the popup's resolved gravity is {@link Gravity#LEFT}, this will
     * display the popup with its top-left corner at (x,y) relative to the
     * anchor view. If the resolved gravity is {@link Gravity#RIGHT}, the
@@ -222,8 +231,11 @@ public class MenuPopupHelper implements MenuHelper {
        return popup;
    }

    private void showPopup(int xOffset, int yOffset, boolean resolveOffsets, boolean showTitle) {
        if (resolveOffsets) {
    private void showPopup(int xOffset, int yOffset, boolean useOffsets, boolean showTitle) {
        final MenuPopup popup = getPopup();
        popup.setShowTitle(showTitle);

        if (useOffsets) {
            // If the resolved drop-down gravity is RIGHT, the popup's right
            // edge will be aligned with the anchor view. Adjust by the anchor
            // width such that the top-right corner is at the X offset.
@@ -232,12 +244,21 @@ public class MenuPopupHelper implements MenuHelper {
            if (hgrav == Gravity.RIGHT) {
                xOffset -= mAnchorView.getWidth();
            }
        }

        final MenuPopup popup = getPopup();
            popup.setHorizontalOffset(xOffset);
            popup.setVerticalOffset(yOffset);
        popup.setShowTitle(showTitle);

            // Set the transition epicenter to be roughly finger (or mouse
            // cursor) sized and centered around the offset position. This
            // will give the appearance that the window is emerging from
            // the touch point.
            final float density = mContext.getResources().getDisplayMetrics().density;
            final int halfSize = (int) (TOUCH_EPICENTER_SIZE_DP * density / 2);
            final Rect epicenter = new Rect(xOffset - halfSize, yOffset - halfSize,
                    xOffset + halfSize, yOffset + halfSize);
            popup.setEpicenterBounds(epicenter);
        }

        popup.show();
    }

Loading