Add an API to listen for window attach/detach events on a View.
Fix bug 3312949 - inconsistent state in MenuPopupHelper
Change-Id: Ie802ada3f8de4cf71c92fcc7c6abce9ba85e7b75
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 6c9e7bb..04a059e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -36,14 +36,15 @@
* @hide
*/
public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener,
- ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener {
+ ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener,
+ View.OnAttachStateChangeListener {
private static final String TAG = "MenuPopupHelper";
private Context mContext;
private ListPopupWindow mPopup;
private MenuBuilder mMenu;
private int mPopupMaxWidth;
- private WeakReference<View> mAnchorView;
+ private View mAnchorView;
private boolean mOverflowOnly;
private ViewTreeObserver mTreeObserver;
@@ -66,13 +67,11 @@
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
mPopupMaxWidth = metrics.widthPixels / 2;
- if (anchorView != null) {
- mAnchorView = new WeakReference<View>(anchorView);
- }
+ mAnchorView = anchorView;
}
public void setAnchorView(View anchor) {
- mAnchorView = new WeakReference<View>(anchor);
+ mAnchorView = anchor;
}
public void show() {
@@ -92,19 +91,19 @@
mPopup.setAdapter(adapter);
mPopup.setModal(true);
- View anchor = mAnchorView != null ? mAnchorView.get() : null;
+ View anchor = mAnchorView;
if (anchor == null && mMenu instanceof SubMenuBuilder) {
SubMenuBuilder subMenu = (SubMenuBuilder) mMenu;
final MenuItemImpl itemImpl = (MenuItemImpl) subMenu.getItem();
anchor = itemImpl.getItemView(MenuBuilder.TYPE_ACTION_BUTTON, null);
- mAnchorView = new WeakReference<View>(anchor);
+ mAnchorView = anchor;
}
if (anchor != null) {
- if (mTreeObserver == null) {
- mTreeObserver = anchor.getViewTreeObserver();
- mTreeObserver.addOnGlobalLayoutListener(this);
- }
+ final boolean addGlobalListener = mTreeObserver == null;
+ mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
+ if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
+ anchor.addOnAttachStateChangeListener(this);
mPopup.setAnchorView(anchor);
} else {
return false;
@@ -125,10 +124,12 @@
public void onDismiss() {
mPopup = null;
- if (mTreeObserver != null && mTreeObserver.isAlive()) {
+ if (mTreeObserver != null) {
+ if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver();
mTreeObserver.removeGlobalOnLayoutListener(this);
+ mTreeObserver = null;
}
- mTreeObserver = null;
+ mAnchorView.removeOnAttachStateChangeListener(this);
}
public boolean isShowing() {
@@ -187,13 +188,8 @@
@Override
public void onGlobalLayout() {
- if (!isShowing()) {
- if (mTreeObserver.isAlive()) {
- mTreeObserver.removeGlobalOnLayoutListener(this);
- }
- mTreeObserver = null;
- } else {
- final View anchor = mAnchorView != null ? mAnchorView.get() : null;
+ if (isShowing()) {
+ final View anchor = mAnchorView;
if (anchor == null || !anchor.isShown()) {
dismiss();
} else if (isShowing()) {
@@ -202,4 +198,17 @@
}
}
}
+
+ @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);
+ }
}