Android Open Source - ActionBarTest Popup Window Compat






From Project

Back to project page ActionBarTest.

License

The source code is released under:

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Defi...

If you think the Android project ActionBarTest listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.actionbarsherlock.internal.widget;
//from  w w w.j  av a  2  s .co m
import java.lang.reflect.Field;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnScrollChangedListener;
import android.widget.PopupWindow;

/**
 * Works around bugs in the handling of {@link ViewTreeObserver} by
 * {@link PopupWindow}.
 * <p>
 * <code>PopupWindow</code> registers an {@link OnScrollChangedListener} with
 * {@link ViewTreeObserver}, but does not keep a reference to the observer
 * instance that it has registers on. This is problematic when the anchor view
 * used by <code>PopupWindow</code> to access the observer is detached from the
 * window, as it will revert from the shared <code>ViewTreeObserver</code> owned
 * by the <code>ViewRoot</code> to a floating one, meaning
 * <code>PopupWindow</code> cannot unregister it's listener anymore and has
 * leaked it into the global observer.
 * <p>
 * This class works around this issue by
 * <ul>
 * <li>replacing <code>PopupWindow.mOnScrollChangedListener</code> with a no-op
 * listener so that any registration or unregistration performed by
 * <code>PopupWindow</code> itself has no effect and causes no leaks.
 * <li>registering the real listener only with the shared
 * <code>ViewTreeObserver</code> and keeping a reference to it to facilitate
 * correct unregistration. The reason for not registering on a floating observer
 * (before a view is attached) is that there is no safe way to get a reference
 * to the shared observer that the floating one will be merged into. This would
 * again cause the listener to leak.
 * </ul>
 */
public class PopupWindowCompat extends PopupWindow {

    private static final Field superListenerField;
    static {
        Field f = null;
        try {
            f = PopupWindow.class.getDeclaredField("mOnScrollChangedListener");
            f.setAccessible(true);
        } catch (NoSuchFieldException e) {
            /* ignored */
        }
        superListenerField = f;
    }

    private static final OnScrollChangedListener NOP = new OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            /* do nothing */
        }
    };

    private OnScrollChangedListener mSuperScrollListener;
    private ViewTreeObserver mViewTreeObserver;

    public PopupWindowCompat() {
        super();
        init();
    }

    public PopupWindowCompat(Context context) {
        super(context);
        init();
    }

    public PopupWindowCompat(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PopupWindowCompat(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    // @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public PopupWindowCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public PopupWindowCompat(int width, int height) {
        super(width, height);
        init();
    }

    public PopupWindowCompat(View contentView) {
        super(contentView);
        init();
    }

    public PopupWindowCompat(View contentView, int width, int height, boolean focusable) {
        super(contentView, width, height, focusable);
        init();
    }

    public PopupWindowCompat(View contentView, int width, int height) {
        super(contentView, width, height);
        init();
    }

    private void init() {
        if (superListenerField != null) {
            try {
                mSuperScrollListener = (OnScrollChangedListener) superListenerField.get(this);
                superListenerField.set(this, NOP);
            } catch (Exception e) {
                mSuperScrollListener = null;
            }
        }
    }

    private void unregisterListener() {
        // Don't do anything if we haven't managed to patch the super listener
        if (mSuperScrollListener != null && mViewTreeObserver != null) {
            if (mViewTreeObserver.isAlive()) {
                mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener);
            }
            mViewTreeObserver = null;
        }
    }

    private void registerListener(View anchor) {
        // Don't do anything if we haven't managed to patch the super listener.
        // And don't bother attaching the listener if the anchor view isn't
        // attached. This means we'll only have to deal with the real VTO owned
        // by the ViewRoot.
        if (mSuperScrollListener != null) {
            ViewTreeObserver vto = (anchor.getWindowToken() != null) ? anchor.getViewTreeObserver()
                    : null;
            if (vto != mViewTreeObserver) {
                if (mViewTreeObserver != null && mViewTreeObserver.isAlive()) {
                    mViewTreeObserver.removeOnScrollChangedListener(mSuperScrollListener);
                }
                if ((mViewTreeObserver = vto) != null) {
                    vto.addOnScrollChangedListener(mSuperScrollListener);
                }
            }
        }
    }

    @Override
    public void showAsDropDown(View anchor, int xoff, int yoff) {
        super.showAsDropDown(anchor, xoff, yoff);
        registerListener(anchor);
    }

    @Override
    public void update(View anchor, int xoff, int yoff, int width, int height) {
        super.update(anchor, xoff, yoff, width, height);
        registerListener(anchor);
    }

    @Override
    public void update(View anchor, int width, int height) {
        super.update(anchor, width, height);
        registerListener(anchor);
    }

    @Override
    public void showAtLocation(View parent, int gravity, int x, int y) {
        super.showAtLocation(parent, gravity, x, y);
        unregisterListener();
    }

    @Override
    public void dismiss() {
        super.dismiss();
        unregisterListener();
    }
}




Java Source Code List

android.support.v4.app.Watson.java
com.actionbarsherlock.ActionBarSherlock.java
com.actionbarsherlock.app.ActionBar.java
com.actionbarsherlock.app.SherlockActivity.java
com.actionbarsherlock.app.SherlockDialogFragment.java
com.actionbarsherlock.app.SherlockExpandableListActivity.java
com.actionbarsherlock.app.SherlockFragmentActivity.java
com.actionbarsherlock.app.SherlockFragment.java
com.actionbarsherlock.app.SherlockListActivity.java
com.actionbarsherlock.app.SherlockListFragment.java
com.actionbarsherlock.app.SherlockPreferenceActivity.java
com.actionbarsherlock.internal.ActionBarSherlockCompat.java
com.actionbarsherlock.internal.ActionBarSherlockNative.java
com.actionbarsherlock.internal.ResourcesCompat.java
com.actionbarsherlock.internal.app.ActionBarImpl.java
com.actionbarsherlock.internal.app.ActionBarWrapper.java
com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorListenerAdapter.java
com.actionbarsherlock.internal.nineoldandroids.animation.AnimatorSet.java
com.actionbarsherlock.internal.nineoldandroids.animation.Animator.java
com.actionbarsherlock.internal.nineoldandroids.animation.FloatEvaluator.java
com.actionbarsherlock.internal.nineoldandroids.animation.FloatKeyframeSet.java
com.actionbarsherlock.internal.nineoldandroids.animation.IntEvaluator.java
com.actionbarsherlock.internal.nineoldandroids.animation.IntKeyframeSet.java
com.actionbarsherlock.internal.nineoldandroids.animation.KeyframeSet.java
com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.java
com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator.java
com.actionbarsherlock.internal.nineoldandroids.animation.PropertyValuesHolder.java
com.actionbarsherlock.internal.nineoldandroids.animation.TypeEvaluator.java
com.actionbarsherlock.internal.nineoldandroids.animation.ValueAnimator.java
com.actionbarsherlock.internal.nineoldandroids.view.NineViewGroup.java
com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy.java
com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout.java
com.actionbarsherlock.internal.nineoldandroids.widget.NineHorizontalScrollView.java
com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout.java
com.actionbarsherlock.internal.view.ActionProviderWrapper.java
com.actionbarsherlock.internal.view.StandaloneActionMode.java
com.actionbarsherlock.internal.view.View_HasStateListenerSupport.java
com.actionbarsherlock.internal.view.View_OnAttachStateChangeListener.java
com.actionbarsherlock.internal.view.menu.ActionMenuItemView.java
com.actionbarsherlock.internal.view.menu.ActionMenuItem.java
com.actionbarsherlock.internal.view.menu.ActionMenuPresenter.java
com.actionbarsherlock.internal.view.menu.ActionMenuView.java
com.actionbarsherlock.internal.view.menu.ActionMenu.java
com.actionbarsherlock.internal.view.menu.BaseMenuPresenter.java
com.actionbarsherlock.internal.view.menu.ListMenuItemView.java
com.actionbarsherlock.internal.view.menu.MenuBuilder.java
com.actionbarsherlock.internal.view.menu.MenuItemImpl.java
com.actionbarsherlock.internal.view.menu.MenuItemWrapper.java
com.actionbarsherlock.internal.view.menu.MenuPopupHelper.java
com.actionbarsherlock.internal.view.menu.MenuPresenter.java
com.actionbarsherlock.internal.view.menu.MenuView.java
com.actionbarsherlock.internal.view.menu.MenuWrapper.java
com.actionbarsherlock.internal.view.menu.SubMenuBuilder.java
com.actionbarsherlock.internal.view.menu.SubMenuWrapper.java
com.actionbarsherlock.internal.widget.AbsActionBarView.java
com.actionbarsherlock.internal.widget.ActionBarContainer.java
com.actionbarsherlock.internal.widget.ActionBarContextView.java
com.actionbarsherlock.internal.widget.ActionBarView.java
com.actionbarsherlock.internal.widget.CapitalizingButton.java
com.actionbarsherlock.internal.widget.CapitalizingTextView.java
com.actionbarsherlock.internal.widget.CollapsibleActionViewWrapper.java
com.actionbarsherlock.internal.widget.IcsAbsSpinner.java
com.actionbarsherlock.internal.widget.IcsAdapterView.java
com.actionbarsherlock.internal.widget.IcsColorDrawable.java
com.actionbarsherlock.internal.widget.IcsLinearLayout.java
com.actionbarsherlock.internal.widget.IcsListPopupWindow.java
com.actionbarsherlock.internal.widget.IcsProgressBar.java
com.actionbarsherlock.internal.widget.IcsSpinner.java
com.actionbarsherlock.internal.widget.IcsToast.java
com.actionbarsherlock.internal.widget.IcsView.java
com.actionbarsherlock.internal.widget.PopupWindowCompat.java
com.actionbarsherlock.internal.widget.ScrollingTabContainerView.java
com.actionbarsherlock.internal.widget.TabsLinearLayout.java
com.actionbarsherlock.view.ActionMode.java
com.actionbarsherlock.view.ActionProvider.java
com.actionbarsherlock.view.CollapsibleActionView.java
com.actionbarsherlock.view.MenuInflater.java
com.actionbarsherlock.view.MenuItem.java
com.actionbarsherlock.view.Menu.java
com.actionbarsherlock.view.SubMenu.java
com.actionbarsherlock.view.Window.java
com.actionbarsherlock.widget.ActivityChooserModel.java
com.actionbarsherlock.widget.ActivityChooserView.java
com.actionbarsherlock.widget.SearchView.java
com.actionbarsherlock.widget.ShareActionProvider.java
com.actionbarsherlock.widget.SuggestionsAdapter.java
com.example.actionbar.MainActivity.java
com.example.actionbar.Map.java
com.robotium.actionbartest.AllTests.java
com.robotium.actionbartest.MainActivityTest.java
com.robotium.actionbartest.MapActivityTest.java