summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/widget/ListPopupWindow.java9
-rw-r--r--core/java/android/widget/PopupWindow.java41
-rw-r--r--core/java/com/android/internal/view/menu/CascadingMenuPopup.java31
3 files changed, 52 insertions, 29 deletions
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 0bde983337f1..3d59f9d429c7 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -75,6 +75,7 @@ public class ListPopupWindow implements ShowableListMenu {
private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
private boolean mDropDownVerticalOffsetSet;
private boolean mIsAnimatedFromAnchor = true;
+ private boolean mOverlapAnchor;
private int mDropDownGravity = Gravity.NO_GRAVITY;
@@ -668,6 +669,7 @@ public class ListPopupWindow implements ShowableListMenu {
mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
mPopup.setTouchInterceptor(mTouchInterceptor);
mPopup.setEpicenterBounds(mEpicenterBounds);
+ mPopup.setOverlapAnchor(mOverlapAnchor);
mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
mDropDownVerticalOffset, mDropDownGravity);
mDropDownList.setSelection(ListView.INVALID_POSITION);
@@ -1241,6 +1243,13 @@ public class ListPopupWindow implements ShowableListMenu {
return listContent + otherHeights;
}
+ /**
+ * @hide
+ */
+ public void setOverlapAnchor(boolean overlap) {
+ mOverlapAnchor = overlap;
+ }
+
private class PopupDataSetObserver extends DataSetObserver {
@Override
public void onChanged() {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 26b3ae2c42fc..9f10531841e3 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -55,6 +55,7 @@ import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import android.view.WindowManagerGlobal;
import com.android.internal.R;
@@ -137,6 +138,7 @@ public class PopupWindow {
private final int[] mTmpDrawingLocation = new int[2];
private final int[] mTmpScreenLocation = new int[2];
+ private final int[] mTmpAppLocation = new int[2];
private final Rect mTempRect = new Rect();
private Context mContext;
@@ -242,6 +244,9 @@ public class PopupWindow {
private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor;
+ private final View.OnLayoutChangeListener mOnLayoutChangeListener =
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> alignToAnchor();
+
private int mAnchorXoff;
private int mAnchorYoff;
private int mAnchoredGravity;
@@ -1238,7 +1243,8 @@ public class PopupWindow {
mIsShowing = true;
mIsDropdown = true;
- final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
+ final WindowManager.LayoutParams p =
+ createPopupLayoutParams(anchor.getApplicationWindowToken());
preparePopup(p);
final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
@@ -1547,13 +1553,21 @@ public class PopupWindow {
}
// Initially, align to the bottom-left corner of the anchor plus offsets.
+ final int[] appScreenLocation = mTmpAppLocation;
+ final View appRootView = getAppRootView(anchor);
+ appRootView.getLocationOnScreen(appScreenLocation);
+
+ final int[] screenLocation = mTmpScreenLocation;
+ anchor.getLocationOnScreen(screenLocation);
+
final int[] drawingLocation = mTmpDrawingLocation;
- anchor.getLocationInWindow(drawingLocation);
+ drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
+ drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
final Rect displayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(displayFrame);
+ appRootView.getWindowVisibleDisplayFrame(displayFrame);
if (width == MATCH_PARENT) {
width = displayFrame.right - displayFrame.left;
}
@@ -1574,9 +1588,6 @@ public class PopupWindow {
outParams.x -= width - anchorWidth;
}
- final int[] screenLocation = mTmpScreenLocation;
- anchor.getLocationOnScreen(screenLocation);
-
// First, attempt to fit the popup vertically without resizing.
final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
@@ -1595,7 +1606,9 @@ public class PopupWindow {
scrollY + height + anchorHeight + yOffset);
if (allowScroll && anchor.requestRectangleOnScreen(r, true)) {
// Reset for the new anchor position.
- anchor.getLocationInWindow(drawingLocation);
+ anchor.getLocationOnScreen(screenLocation);
+ drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
+ drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
outParams.x = drawingLocation[0] + xOffset;
outParams.y = drawingLocation[1] + anchorHeight + yOffset;
@@ -1793,7 +1806,8 @@ public class PopupWindow {
Rect displayFrame = null;
final Rect visibleDisplayFrame = new Rect();
- anchor.getWindowVisibleDisplayFrame(visibleDisplayFrame);
+ final View appView = getAppRootView(anchor);
+ appView.getWindowVisibleDisplayFrame(visibleDisplayFrame);
if (ignoreBottomDecorations) {
// In the ignore bottom decorations case we want to
// still respect all other decorations so we use the inset visible
@@ -2240,6 +2254,7 @@ public class PopupWindow {
final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
if (anchorRoot != null) {
anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ anchorRoot.removeOnLayoutChangeListener(mOnLayoutChangeListener);
}
mAnchor = null;
@@ -2258,6 +2273,7 @@ public class PopupWindow {
final View anchorRoot = anchor.getRootView();
anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
+ anchorRoot.addOnLayoutChangeListener(mOnLayoutChangeListener);
mAnchor = new WeakReference<>(anchor);
mAnchorRoot = new WeakReference<>(anchorRoot);
@@ -2281,6 +2297,15 @@ public class PopupWindow {
}
}
+ private View getAppRootView(View anchor) {
+ final View appWindowView = WindowManagerGlobal.getInstance().getWindowView(
+ anchor.getApplicationWindowToken());
+ if (appWindowView != null) {
+ return appWindowView;
+ }
+ return anchor.getRootView();
+ }
+
private class PopupDecorView extends FrameLayout {
private TransitionListenerAdapter mPendingExitListener;
diff --git a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
index 1de0af6f31df..29f67b6ca70b 100644
--- a/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
+++ b/core/java/com/android/internal/view/menu/CascadingMenuPopup.java
@@ -381,6 +381,7 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey
if (parentView != null) {
// This menu is a cascading submenu anchored to a parent view.
+ popupWindow.setAnchorView(parentView);
popupWindow.setTouchModal(false);
popupWindow.setEnterTransition(null);
@@ -388,42 +389,30 @@ final class CascadingMenuPopup extends MenuPopup implements MenuPresenter, OnKey
final boolean showOnRight = nextMenuPosition == HORIZ_POSITION_RIGHT;
mLastPosition = nextMenuPosition;
- // A popup anchored to mAnchorView with (0,0) offset would be shown at this position.
- final int[] offsetOrigin = new int[2];
- mAnchorView.getLocationOnScreen(offsetOrigin);
- offsetOrigin[1] += mAnchorView.getHeight();
-
- final int[] parentViewScreenLocation = new int[2];
- parentView.getLocationOnScreen(parentViewScreenLocation);
-
- // Translate the parent view location into the offset coordinate space.
- // If used as horizontal/vertical offsets, these values would position the submenu
- // at the exact same position as the parent item.
- final int parentOffsetLeft = parentViewScreenLocation[0] - offsetOrigin[0];
- final int parentOffsetTop = parentViewScreenLocation[1] - offsetOrigin[1];
-
- // Adjust the horizontal offset to display the submenu to the right or to the left
+ // Compute the horizontal offset to display the submenu to the right or to the left
// of the parent item.
// By now, mDropDownGravity is the resolved absolute gravity, so
// this should work in both LTR and RTL.
final int x;
if ((mDropDownGravity & Gravity.RIGHT) == Gravity.RIGHT) {
if (showOnRight) {
- x = parentOffsetLeft + menuWidth;
+ x = menuWidth;
} else {
- x = parentOffsetLeft - parentView.getWidth();
+ x = -parentView.getWidth();
}
} else {
if (showOnRight) {
- x = parentOffsetLeft + parentView.getWidth();
+ x = parentView.getWidth();
} else {
- x = parentOffsetLeft - menuWidth;
+ x = -menuWidth;
}
}
popupWindow.setHorizontalOffset(x);
- // Use the same vertical offset as the parent item.
- popupWindow.setVerticalOffset(parentOffsetTop);
+ // Align with the top edge of the parent view (or the bottom edge when the submenu is
+ // flipped vertically).
+ popupWindow.setOverlapAnchor(true);
+ popupWindow.setVerticalOffset(0);
} else {
if (mHasXOffset) {
popupWindow.setHorizontalOffset(mXOffset);