Loading core/java/android/widget/ListPopupWindow.java +20 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading core/java/android/widget/PopupWindow.java +42 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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) { Loading core/java/com/android/internal/view/menu/CascadingMenuPopup.java +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading core/java/com/android/internal/view/menu/MenuPopup.java +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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). Loading core/java/com/android/internal/view/menu/MenuPopupHelper.java +27 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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. Loading @@ -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 Loading
core/java/android/widget/ListPopupWindow.java +20 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading
core/java/android/widget/PopupWindow.java +42 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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) { Loading
core/java/com/android/internal/view/menu/CascadingMenuPopup.java +4 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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); Loading
core/java/com/android/internal/view/menu/MenuPopup.java +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading @@ -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). Loading
core/java/com/android/internal/view/menu/MenuPopupHelper.java +27 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading Loading @@ -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 Loading Loading @@ -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. Loading @@ -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