diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 1436bdb3cbd96..d096baf3c9439 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -210,6 +210,21 @@ public class PopupWindow { com.android.internal.R.attr.state_above_anchor }; + private final OnAttachStateChangeListener mOnAnchorDetachedListener = + new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + // Anchor might have been reattached in a different position. + alignToAnchor(); + } + + @Override + public void onViewDetachedFromWindow(View v) { + // Leave the popup in its current position. + // The anchor might become attached again. + } + }; + private final OnAttachStateChangeListener mOnAnchorRootDetachedListener = new OnAttachStateChangeListener() { @Override @@ -225,20 +240,7 @@ public class PopupWindow { private WeakReference mAnchorRoot; private boolean mIsAnchorRootAttached; - private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() { - @Override - public void onScrollChanged() { - final View anchor = mAnchor != null ? mAnchor.get() : null; - if (anchor != null && mDecorView != null) { - final WindowManager.LayoutParams p = (WindowManager.LayoutParams) - mDecorView.getLayoutParams(); - - updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff, - p.width, p.height, mAnchoredGravity, false)); - update(p.x, p.y, -1, -1, true); - } - } - }; + private final OnScrollChangedListener mOnScrollChangedListener = this::alignToAnchor; private int mAnchorXoff; private int mAnchorYoff; @@ -2217,6 +2219,7 @@ public class PopupWindow { if (anchor != null) { final ViewTreeObserver vto = anchor.getViewTreeObserver(); vto.removeOnScrollChangedListener(mOnScrollChangedListener); + anchor.removeOnAttachStateChangeListener(mOnAnchorDetachedListener); } final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null; @@ -2236,6 +2239,7 @@ public class PopupWindow { if (vto != null) { vto.addOnScrollChangedListener(mOnScrollChangedListener); } + anchor.addOnAttachStateChangeListener(mOnAnchorDetachedListener); final View anchorRoot = anchor.getRootView(); anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener); @@ -2250,6 +2254,18 @@ public class PopupWindow { mAnchoredGravity = gravity; } + private void alignToAnchor() { + final View anchor = mAnchor != null ? mAnchor.get() : null; + if (anchor != null && anchor.isAttachedToWindow() && mDecorView != null) { + final WindowManager.LayoutParams p = (WindowManager.LayoutParams) + mDecorView.getLayoutParams(); + + updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff, + p.width, p.height, mAnchoredGravity, false)); + update(p.x, p.y, -1, -1, true); + } + } + private class PopupDecorView extends FrameLayout { private TransitionListenerAdapter mPendingExitListener;