PopupWindow.java revision 259c2840691a79634ffd8f63291ec21c21819542
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport com.android.internal.R;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.Context;
22a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport android.content.res.Resources;
2375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.res.TypedArray;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.StateListDrawable;
2846e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brownimport android.os.Build;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
305435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.Transition;
315435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.Transition.EpicenterCallback;
328fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.transition.Transition.TransitionListener;
338fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.transition.Transition.TransitionListenerAdapter;
345435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionInflater;
355435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionManager;
365435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionSet;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
38c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.Gravity;
39c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.KeyEvent;
40c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.MotionEvent;
41c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View;
42a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport android.view.View.OnTouchListener;
43c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewGroup;
448fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.view.ViewParent;
45c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewTreeObserver;
468fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
47c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewTreeObserver.OnScrollChangedListener;
48a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport android.view.WindowManager;
49259c2840691a79634ffd8f63291ec21c21819542Alan Viveretteimport android.view.WindowManager.LayoutParams;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport java.lang.ref.WeakReference;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>A popup window that can be used to display an arbitrary view. The popup
557ed189e457b16c06b0425bd28aeeb1df5c8ff5b8Scott Kennedy * window is a floating container that appears on top of the current
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * activity.</p>
575435a30ae552391f14009c4459731ae149675b18Alan Viverette *
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.AutoCompleteTextView
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.Spinner
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PopupWindow {
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
63e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method should be based on the focusability of the popup.  That is
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if it is focusable than it needs to work with the input method, else
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it doesn't.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
695435a30ae552391f14009c4459731ae149675b18Alan Viverette
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
71e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed so that the user can also operate
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the input method while it is shown.
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NEEDED = 1;
775435a30ae552391f14009c4459731ae149675b18Alan Viverette
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
79e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed to use as much space on the
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen as needed, regardless of whether this covers the input method.
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NOT_NEEDED = 2;
8554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
8654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private static final int DEFAULT_ANCHORED_GRAVITY = Gravity.TOP | Gravity.START;
8754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
885435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
895435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Default animation style indicating that separate animations should be
905435a30ae552391f14009c4459731ae149675b18Alan Viverette     * used for top/bottom anchoring states.
915435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
925435a30ae552391f14009c4459731ae149675b18Alan Viverette    private static final int ANIMATION_STYLE_DEFAULT = -1;
935435a30ae552391f14009c4459731ae149675b18Alan Viverette
945435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final int[] mDrawingLocation = new int[2];
955435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final int[] mScreenLocation = new int[2];
965435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final Rect mTempRect = new Rect();
975435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final Rect mAnchorBounds = new Rect();
985435a30ae552391f14009c4459731ae149675b18Alan Viverette
99448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private Context mContext;
100448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private WindowManager mWindowManager;
1015435a30ae552391f14009c4459731ae149675b18Alan Viverette
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsShowing;
1038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette    private boolean mIsTransitioningToDismiss;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsDropdown;
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1065435a30ae552391f14009c4459731ae149675b18Alan Viverette    /** View that handles event dispatch and content transitions. */
1075435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView mDecorView;
1085435a30ae552391f14009c4459731ae149675b18Alan Viverette
1095435a30ae552391f14009c4459731ae149675b18Alan Viverette    /** The contents of the popup. */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mContentView;
1115435a30ae552391f14009c4459731ae149675b18Alan Viverette
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFocusable;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
1147eab094722af54717859b7dcce3cc050f059e00bDianne Hackborn    private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mTouchable = true;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOutsideTouchable = false;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mClippingEnabled = true;
11846e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown    private int mSplitTouchEnabled = -1;
119ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    private boolean mLayoutInScreen;
12056c2d337e02a275397fc9d0460dca90977f199acAdam Powell    private boolean mClipToScreen;
121348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    private boolean mAllowScrollingAnchorParent = true;
1220bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    private boolean mLayoutInsetDecor = false;
123e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    private boolean mNotTouchModal;
124393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecor = true;
125393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecorSet = false;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnTouchListener mTouchInterceptor;
128393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mWidthMode;
130259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mWidth = LayoutParams.WRAP_CONTENT;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastWidth;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mHeightMode;
133259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mHeight = LayoutParams.WRAP_CONTENT;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastHeight;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPopupWidth;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPopupHeight;
13856c2d337e02a275397fc9d0460dca90977f199acAdam Powell
139ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    private float mElevation;
140ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBackground;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mAboveAnchorBackgroundDrawable;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBelowAnchorBackgroundDrawable;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1455435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mEnterTransition;
1465435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mExitTransition;
147560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAboveAnchor;
149574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
1505435a30ae552391f14009c4459731ae149675b18Alan Viverette
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnDismissListener mOnDismissListener;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIgnoreCheekPress = false;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1545435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
1555435a30ae552391f14009c4459731ae149675b18Alan Viverette
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.attr.state_above_anchor
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WeakReference<View> mAnchor;
161560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1625435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final EpicenterCallback mEpicenterCallback = new EpicenterCallback() {
1635435a30ae552391f14009c4459731ae149675b18Alan Viverette        @Override
1645435a30ae552391f14009c4459731ae149675b18Alan Viverette        public Rect onGetEpicenter(Transition transition) {
165df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette            final View anchor = mAnchor != null ? mAnchor.get() : null;
1667878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            final View decor = mDecorView;
1677878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            if (anchor == null || decor == null) {
1687878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette                return null;
1697878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            }
1707878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
1717878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            final Rect anchorBounds = mAnchorBounds;
172df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette            final int[] anchorLocation = anchor.getLocationOnScreen();
1737878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            final int[] popupLocation = mDecorView.getLocationOnScreen();
1747878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
1757878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            // Compute the position of the anchor relative to the popup.
1767878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            anchorBounds.set(0, 0, anchor.getWidth(), anchor.getHeight());
1777878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            anchorBounds.offset(anchorLocation[0] - popupLocation[0],
1787878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette                    anchorLocation[1] - popupLocation[1]);
1797878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
1807878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            return anchorBounds;
1815435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
1825435a30ae552391f14009c4459731ae149675b18Alan Viverette    };
1835435a30ae552391f14009c4459731ae149675b18Alan Viverette
1845435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
1855435a30ae552391f14009c4459731ae149675b18Alan Viverette        @Override
1865435a30ae552391f14009c4459731ae149675b18Alan Viverette        public void onScrollChanged() {
1875435a30ae552391f14009c4459731ae149675b18Alan Viverette            final View anchor = mAnchor != null ? mAnchor.get() : null;
1885435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (anchor != null && mDecorView != null) {
1895435a30ae552391f14009c4459731ae149675b18Alan Viverette                final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
1905435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mDecorView.getLayoutParams();
1915435a30ae552391f14009c4459731ae149675b18Alan Viverette
1925435a30ae552391f14009c4459731ae149675b18Alan Viverette                updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
1935435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mAnchoredGravity));
1945435a30ae552391f14009c4459731ae149675b18Alan Viverette                update(p.x, p.y, -1, -1, true);
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1965435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
1975435a30ae552391f14009c4459731ae149675b18Alan Viverette    };
198560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1995435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorXoff;
2005435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorYoff;
2015435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchoredGravity;
202560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette    private boolean mOverlapAnchor;
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
204b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private boolean mPopupViewInitialLayoutDirectionInherited;
205b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context) {
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, null);
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context, AttributeSet attrs) {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, attrs, com.android.internal.R.attr.popupWindowStyle);
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
229617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
230617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
231c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
2325435a30ae552391f14009c4459731ae149675b18Alan Viverette
233c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
234c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Create a new, empty, non focusable popup window of dimension (0,0).</p>
2355435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
236c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>The popup does not provide a background.</p>
237c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
238c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
24075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
242617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(
243ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                attrs, R.styleable.PopupWindow, defStyleAttr, defStyleRes);
244ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        final Drawable bg = a.getDrawable(R.styleable.PopupWindow_popupBackground);
245ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = a.getDimension(R.styleable.PopupWindow_popupElevation, 0);
246560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
247c3808b5dc7d5873d04e8a0a247b179b2757764baAdam Powell
2485435a30ae552391f14009c4459731ae149675b18Alan Viverette        // Preserve default behavior from Gingerbread. If the animation is
2495435a30ae552391f14009c4459731ae149675b18Alan Viverette        // undefined or explicitly specifies the Gingerbread animation style,
2505435a30ae552391f14009c4459731ae149675b18Alan Viverette        // use a sentinel value.
2515435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupAnimationStyle)) {
2525435a30ae552391f14009c4459731ae149675b18Alan Viverette            final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, 0);
2535435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (animStyle == R.style.Animation_PopupWindow) {
2545435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2555435a30ae552391f14009c4459731ae149675b18Alan Viverette            } else {
2565435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = animStyle;
2575435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
2585435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
2595435a30ae552391f14009c4459731ae149675b18Alan Viverette            mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2605435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2615435a30ae552391f14009c4459731ae149675b18Alan Viverette
2625435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition enterTransition = getTransition(a.getResourceId(
2635435a30ae552391f14009c4459731ae149675b18Alan Viverette                R.styleable.PopupWindow_popupEnterTransition, 0));
2645435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition exitTransition;
2655435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupExitTransition)) {
2665435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = getTransition(a.getResourceId(
2675435a30ae552391f14009c4459731ae149675b18Alan Viverette                    R.styleable.PopupWindow_popupExitTransition, 0));
2685435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
2695435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = enterTransition == null ? null : enterTransition.clone();
2705435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
273ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
2745435a30ae552391f14009c4459731ae149675b18Alan Viverette        setEnterTransition(enterTransition);
2755435a30ae552391f14009c4459731ae149675b18Alan Viverette        setExitTransition(exitTransition);
276ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        setBackgroundDrawable(bg);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow() {
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, 0, 0);
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window are (0,0).</p>
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView) {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, 0, 0);
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window. The dimension of the
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window must be passed to this constructor.</p>
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(int width, int height) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, width, height);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window must be passed to
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this constructor.</p>
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView, int width, int height) {
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, width, height, false);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new popup window which can display the <tt>contentView</tt>.
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The dimension of the window must be passed to this constructor.</p>
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup can be focused, false otherwise
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
344448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    public PopupWindow(View contentView, int width, int height, boolean focusable) {
345448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (contentView != null) {
346448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = contentView.getContext();
347448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
348448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
349393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setContentView(contentView);
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setWidth(width);
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeight(height);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusable(focusable);
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3565435a30ae552391f14009c4459731ae149675b18Alan Viverette    public void setEnterTransition(Transition enterTransition) {
3575435a30ae552391f14009c4459731ae149675b18Alan Viverette        mEnterTransition = enterTransition;
3585435a30ae552391f14009c4459731ae149675b18Alan Viverette
3595435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (mEnterTransition != null) {
3605435a30ae552391f14009c4459731ae149675b18Alan Viverette            mEnterTransition.setEpicenterCallback(mEpicenterCallback);
3615435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
3625435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
3635435a30ae552391f14009c4459731ae149675b18Alan Viverette
3645435a30ae552391f14009c4459731ae149675b18Alan Viverette    public void setExitTransition(Transition exitTransition) {
3655435a30ae552391f14009c4459731ae149675b18Alan Viverette        mExitTransition = exitTransition;
3665435a30ae552391f14009c4459731ae149675b18Alan Viverette
3675435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (mExitTransition != null) {
3685435a30ae552391f14009c4459731ae149675b18Alan Viverette            mExitTransition.setEpicenterCallback(mEpicenterCallback);
3695435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
3705435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
3715435a30ae552391f14009c4459731ae149675b18Alan Viverette
3725435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition getTransition(int resId) {
3735435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (resId != 0 && resId != R.transition.no_transition) {
3745435a30ae552391f14009c4459731ae149675b18Alan Viverette            final TransitionInflater inflater = TransitionInflater.from(mContext);
3755435a30ae552391f14009c4459731ae149675b18Alan Viverette            final Transition transition = inflater.inflateTransition(resId);
3765435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (transition != null) {
3775435a30ae552391f14009c4459731ae149675b18Alan Viverette                final boolean isEmpty = transition instanceof TransitionSet
3785435a30ae552391f14009c4459731ae149675b18Alan Viverette                        && ((TransitionSet) transition).getTransitionCount() == 0;
3795435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (!isEmpty) {
3805435a30ae552391f14009c4459731ae149675b18Alan Viverette                    return transition;
3815435a30ae552391f14009c4459731ae149675b18Alan Viverette                }
3825435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
3835435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
3845435a30ae552391f14009c4459731ae149675b18Alan Viverette        return null;
3855435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
3865435a30ae552391f14009c4459731ae149675b18Alan Viverette
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
388ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Return the drawable used as the popup window's background.
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
390ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the background drawable or {@code null} if not set
391ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setBackgroundDrawable(Drawable)
392ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getBackground() {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBackground;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
399ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the background drawable for this popup window. The background
400ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * can be set to {@code null}.
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param background the popup's background
403ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getBackground()
404ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setBackgroundDrawable(Drawable background) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBackground = background;
408ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
409ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // If this is a StateListDrawable, try to find and store the drawable to be
410ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed above its anchor view, and the one to be
411ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed below its anchor view. We extract
412ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // the drawables ourselves to work around a problem with using refreshDrawableState
413ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // that it will take into account the padding of all drawables specified in a
414ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // StateListDrawable, thus adding superfluous padding to drop-down views.
415ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        //
416ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // We assume a StateListDrawable will have a drawable for ABOVE_ANCHOR_STATE_SET and
417ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // at least one other drawable, intended for the 'below-anchor state'.
418ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        if (mBackground instanceof StateListDrawable) {
419ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            StateListDrawable stateList = (StateListDrawable) mBackground;
420ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
421ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Find the above-anchor view - this one's easy, it should be labeled as such.
422ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int aboveAnchorStateIndex = stateList.getStateDrawableIndex(ABOVE_ANCHOR_STATE_SET);
423ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
424ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Now, for the below-anchor view, look for any other drawable specified in the
425ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // StateListDrawable which is not for the above-anchor state and use that.
426ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int count = stateList.getStateCount();
427ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int belowAnchorStateIndex = -1;
428ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            for (int i = 0; i < count; i++) {
429ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                if (i != aboveAnchorStateIndex) {
430ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    belowAnchorStateIndex = i;
431ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    break;
432ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                }
433ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
434ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
435ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Store the drawables we found, if we found them. Otherwise, set them both
436ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // to null so that we'll just use refreshDrawableState.
437ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            if (aboveAnchorStateIndex != -1 && belowAnchorStateIndex != -1) {
438ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = stateList.getStateDrawable(aboveAnchorStateIndex);
439ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = stateList.getStateDrawable(belowAnchorStateIndex);
440ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            } else {
441ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = null;
442ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = null;
443ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
444ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        }
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
448ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the elevation for this popup window in pixels
449ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setElevation(float)
450ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
451ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
452ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public float getElevation() {
453ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        return mElevation;
454ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
455ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
456ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
457ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the elevation for this popup window.
458ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     *
459ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @param elevation the popup's elevation in pixels
460ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getElevation()
461ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
462ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
463ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public void setElevation(float elevation) {
464ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = elevation;
465ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
466ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
467ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the animation style to use the popup appears and disappears</p>
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the animation style to use the popup appears and disappears
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAnimationStyle() {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
475393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
47754ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * Set the flag on popup to ignore cheek press events; by default this flag
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is set to false
47954ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * which means the popup will not ignore cheek press dispatch events.
4805435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
484393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setIgnoreCheekPress() {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIgnoreCheekPress = true;
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4905435a30ae552391f14009c4459731ae149675b18Alan Viverette
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the animation style resource for this popup.</p>
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param animationStyle animation style to use when the popup appears
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      and disappears.  Set to -1 for the default animation, 0 for no
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      animation, or a resource identifier for an explicit animation.
5025435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAnimationStyle(int animationStyle) {
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationStyle = animationStyle;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5085435a30ae552391f14009c4459731ae149675b18Alan Viverette
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the view used as the content of the popup window.</p>
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a {@link android.view.View} representing the popup's content
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setContentView(android.view.View)
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getContentView() {
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContentView;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the popup's content. The content is represented by an instance
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of {@link android.view.View}.</p>
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
52481f08086b44a117097960195d2c9072e29644962Gilles Debunne     * <p>This method has no effect if called when the popup is showing.</p>
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the new content for the popup
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getContentView()
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setContentView(View contentView) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing()) {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContentView = contentView;
537448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
5380c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext == null && mContentView != null) {
539448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = mContentView.getContext();
540448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
541448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
5420c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mWindowManager == null && mContentView != null) {
543448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
544448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
545393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
546393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // Setting the default for attachedInDecor based on SDK version here
547393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // instead of in the constructor since we might not have the context
548393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // object in the constructor. We only want to set default here if the
549393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // app hasn't already set the attachedInDecor.
550393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mContext != null && !mAttachedInDecorSet) {
551393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // Attach popup window in decor frame of parent window by default for
552393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current
553393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // behavior of not attaching to decor frame for older SDKs.
554393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion
555393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale                    >= Build.VERSION_CODES.LOLLIPOP_MR1);
556393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
557393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set a callback for all touch events being dispatched to the popup
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window.
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchInterceptor(OnTouchListener l) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchInterceptor = l;
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
567393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether the popup window can grab the focus.</p>
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is focusable, false otherwise
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setFocusable(boolean)
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isFocusable() {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFocusable;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the focusability of the popup window. When focusable, the
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will grab the focus from the current focused widget if the popup
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * contains a focusable {@link android.view.View}.  By default a popup
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is not focusable.</p>
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup should grab focus, false otherwise.
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isFocusable()
5925435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFocusable(boolean focusable) {
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFocusable = focusable;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the current value in {@link #setInputMethodMode(int)}.
6015435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setInputMethodMode(int)
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getInputMethodMode() {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputMethodMode;
6065435a30ae552391f14009c4459731ae149675b18Alan Viverette
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6085435a30ae552391f14009c4459731ae149675b18Alan Viverette
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control how the popup operates with an input method: one of
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #INPUT_METHOD_NOT_NEEDED}.
6135435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6175435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getInputMethodMode()
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethodMode(int mode) {
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputMethodMode = mode;
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
624374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
625374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
626374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Sets the operating mode for the soft input area.
627374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
628374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @param mode The desired mode, see
629374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
630374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        for the full list
631374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
632374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
633374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #getSoftInputMode()
634374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
635374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public void setSoftInputMode(int mode) {
636374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        mSoftInputMode = mode;
637374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
638374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
639374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
640374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Returns the current value in {@link #setSoftInputMode(int)}.
641374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
642374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #setSoftInputMode(int)
643374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
644374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
645374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public int getSoftInputMode() {
646374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        return mSoftInputMode;
647374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
6485435a30ae552391f14009c4459731ae149675b18Alan Viverette
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window receives touch events.</p>
6515435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is touchable, false otherwise
6535435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setTouchable(boolean)
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isTouchable() {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTouchable;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the touchability of the popup window. When touchable, the
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will receive touch events, otherwise touch events will go to the
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window below it. By default the window is touchable.</p>
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive touch events, false otherwise
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isTouchable()
6725435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchable(boolean touchable) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchable = touchable;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window will be informed of touch events
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * outside of its window.</p>
6825435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is outside touchable, false otherwise
6845435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setOutsideTouchable(boolean)
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isOutsideTouchable() {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOutsideTouchable;
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Controls whether the pop-up will be informed of touch events outside
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of its window.  This only makes sense for pop-ups that are touchable
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but not focusable, which means touches outside of the window will
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be delivered to the window behind.  The default is false.</p>
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive outside
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * touch events, false otherwise
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isOutsideTouchable()
7055435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOutsideTouchable(boolean touchable) {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOutsideTouchable = touchable;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether clipping of the popup window is enabled.</p>
7145435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the clipping is enabled, false otherwise
7165435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setClippingEnabled(boolean)
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isClippingEnabled() {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mClippingEnabled;
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Allows the popup window to extend beyond the bounds of the screen. By default the
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is clipped to the screen boundaries. Setting this to false will allow windows to be
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accurately positioned.</p>
7275435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param enabled false if the window should be allowed to extend outside of the screen
7335435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isClippingEnabled()
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setClippingEnabled(boolean enabled) {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mClippingEnabled = enabled;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
74256c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * Clip this popup window to the screen, but not to the containing window.
74356c2d337e02a275397fc9d0460dca90977f199acAdam Powell     *
74456c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @param enabled True to clip to the screen.
74556c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @hide
74656c2d337e02a275397fc9d0460dca90977f199acAdam Powell     */
74756c2d337e02a275397fc9d0460dca90977f199acAdam Powell    public void setClipToScreenEnabled(boolean enabled) {
74856c2d337e02a275397fc9d0460dca90977f199acAdam Powell        mClipToScreen = enabled;
74956c2d337e02a275397fc9d0460dca90977f199acAdam Powell        setClippingEnabled(!enabled);
75056c2d337e02a275397fc9d0460dca90977f199acAdam Powell    }
751348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell
752348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    /**
753348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * Allow PopupWindow to scroll the anchor's parent to provide more room
754348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * for the popup. Enabled by default.
755348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     *
756348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * @param enabled True to scroll the anchor's parent when more room is desired by the popup.
757348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     */
758348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    void setAllowScrollingAnchorParent(boolean enabled) {
759348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mAllowScrollingAnchorParent = enabled;
760348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    }
7615435a30ae552391f14009c4459731ae149675b18Alan Viverette
76256c2d337e02a275397fc9d0460dca90977f199acAdam Powell    /**
76301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Indicates whether the popup window supports splitting touches.</p>
7645435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
76501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @return true if the touch splitting is enabled, false otherwise
7665435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
76701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #setSplitTouchEnabled(boolean)
76801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
76901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public boolean isSplitTouchEnabled() {
77046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (mSplitTouchEnabled < 0 && mContext != null) {
77146e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown            return mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
77246e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        }
77346e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        return mSplitTouchEnabled == 1;
77401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
77501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
77601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
77701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Allows the popup window to split touches across other windows that also
77846e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * support split touch.  When this flag is false, the first pointer
77901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * that goes down determines the window to which all subsequent touches
78046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * go until all pointers go up.  When this flag is true, each pointer
78101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * (not necessarily the first) that goes down determines the window
78201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to which all subsequent touches of that pointer will go until that
78301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * pointer goes up thereby enabling touches with multiple pointers
78401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to be split across multiple windows.</p>
78501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     *
78601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @param enabled true if the split touches should be enabled, false otherwise
78701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #isSplitTouchEnabled()
78801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
78901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public void setSplitTouchEnabled(boolean enabled) {
79046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        mSplitTouchEnabled = enabled ? 1 : 0;
79101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
79201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
79301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
794ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Indicates whether the popup window will be forced into using absolute screen coordinates
795ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * for positioning.</p>
796ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
797ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @return true if the window will always be positioned in screen coordinates.
798ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
799ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
800ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public boolean isLayoutInScreenEnabled() {
801ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        return mLayoutInScreen;
802ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
803ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
804ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
805ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Allows the popup window to force the flag
806ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior.
807ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * This will cause the popup to be positioned in absolute screen coordinates.</p>
808ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
809ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @param enabled true if the popup should always be positioned in screen coordinates
810ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
811ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
812ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public void setLayoutInScreenEnabled(boolean enabled) {
813ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        mLayoutInScreen = enabled;
814ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
815ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
816ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
817393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>Indicates whether the popup window will be attached in the decor frame of its parent
818393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * window.
819393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
820393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @return true if the window will be attached to the decor frame of its parent window.
821393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
822393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see #setAttachedInDecor(boolean)
823393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
824393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
825393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public boolean isAttachedInDecor() {
826393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        return mAttachedInDecor;
827393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
828393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
829393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
830393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>This will attach the popup window to the decor frame of the parent window to avoid
831393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * overlaping with screen decorations like the navigation bar. Overrides the default behavior of
832393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}.
833393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
834393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or
835393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * greater and cleared on lesser SDK versions.
836393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
837393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @param enabled true if the popup should be attached to the decor frame of its parent window.
838393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
839393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
840393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
841393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public void setAttachedInDecor(boolean enabled) {
842393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecor = enabled;
843393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecorSet = true;
844393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
845393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
846393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
8470bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * Allows the popup window to force the flag
8480bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
8490bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * This will cause the popup to inset its content to account for system windows overlaying
8500bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * the screen, such as the status bar.
8510bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
8520bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
8530bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
8540bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @param enabled true if the popup's views should inset content to account for system windows,
8550bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *                the way that decor views behave for full-screen windows.
8560bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @hide
8570bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     */
8580bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    public void setLayoutInsetDecor(boolean enabled) {
8590bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        mLayoutInsetDecor = enabled;
8600bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    }
8610bd1d0a15294345bf88b20df28466907f982cec7Adam Powell
8620bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    /**
863574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * Set the layout type for this window. Should be one of the TYPE constants defined in
864574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * {@link WindowManager.LayoutParams}.
865574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     *
866574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @param layoutType Layout type for this window.
867574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @hide
868574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
869574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public void setWindowLayoutType(int layoutType) {
870574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        mWindowLayoutType = layoutType;
871574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
872574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
873574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
874574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @return The layout type for this window.
875574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @hide
876574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
877574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public int getWindowLayoutType() {
878574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        return mWindowLayoutType;
879574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
880574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
881574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
882e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * Set whether this window is touch modal or if outside touches will be sent to
883e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * other windows behind it.
884e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * @hide
885e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     */
886e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    public void setTouchModal(boolean touchModal) {
887e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        mNotTouchModal = !touchModal;
888e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    }
889e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell
890e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    /**
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the width and height measure specs that are given to the
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window manager by the popup.  By default these are 0, meaning that
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the current width or height is requested as an explicit size from
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the window manager.  You can supply
8955435a30ae552391f14009c4459731ae149675b18Alan Viverette     * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or
896980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * spec supplied instead, replacing the absolute width and height that
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * has been set in the popup.</p>
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown.</p>
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param widthSpec an explicit width measure spec mode, either
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
905980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * width.
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param heightSpec an explicit height measure spec mode, either
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
909980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * height.
911259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *
912259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @deprecated Use {@link #setWidth(int)} and {@link #setHeight(int)}.
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
914259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    @Deprecated
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWindowLayoutMode(int widthSpec, int heightSpec) {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidthMode = widthSpec;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeightMode = heightSpec;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9195435a30ae552391f14009c4459731ae149675b18Alan Viverette
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
921259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Returns the popup's height MeasureSpec.
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the height MeasureSpec of the popup
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHeight(int)
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getHeight() {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeight;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
931259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Sets the popup's height MeasureSpec.
932259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
933259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
934259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the height MeasureSpec of the popup
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getHeight()
9385435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHeight(int height) {
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeight = height;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
945259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Returns the popup's width MeasureSpec.
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the width MeasureSpec of the popup
9485435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #setWidth(int)
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWidth() {
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWidth;
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
955259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Sets the popup's width MeasureSpec.
956259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
957259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
958259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the width MeasureSpec of the popup
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getWidth()
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWidth(int width) {
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidth = width;
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
96975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Sets whether the popup window should overlap its anchor view when
97075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
97175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
97275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the popup is showing, calling this method will take effect only
97375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the next time the popup is shown.
97475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
97575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @param overlapAnchor Whether the popup should overlap its anchor.
97675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
97775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #getOverlapAnchor()
97875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #isShowing()
97975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
98075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public void setOverlapAnchor(boolean overlapAnchor) {
98175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mOverlapAnchor = overlapAnchor;
98275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
98375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
98475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
98575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Returns whether the popup window should overlap its anchor view when
98675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
98775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
98875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @return Whether the popup should overlap its anchor.
98975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
99075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #setOverlapAnchor(boolean)
99175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
99275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public boolean getOverlapAnchor() {
99375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        return mOverlapAnchor;
99475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
99575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
99675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether this popup window is showing on screen.</p>
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is showing, false otherwise
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowing() {
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsShowing;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Display the content view in a popup window at the specified location. If the popup window
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams}
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for more information on how gravity and the x and y parameters are related. Specifying
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>Gravity.LEFT | Gravity.TOP</code>.
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </p>
10135435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity the gravity which controls the placement of the popup window
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the popup's x location offset
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the popup's y location offset
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAtLocation(View parent, int gravity, int x, int y) {
10208ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell        showAtLocation(parent.getWindowToken(), gravity, x, y);
10218ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    }
10228ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell
10238ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    /**
10248ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * Display the content view in a popup window at the specified location.
10258ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
10268ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param token Window token to use for creating the new window
10278ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param gravity the gravity which controls the placement of the popup window
10288ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param x the popup's x location offset
10298ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param y the popup's y location offset
10308ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
10318ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @hide Internal use only. Applications should use
10328ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *       {@link #showAtLocation(View, int, int, int)} instead.
10338ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     */
10348ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    public void showAtLocation(IBinder token, int gravity, int x, int y) {
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1040e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterForScrollChanged();
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = false;
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1046e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(token);
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
1048e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1049e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Only override the default if some gravity was specified.
1050e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (gravity != Gravity.NO_GRAVITY) {
1051e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.gravity = gravity;
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1053e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.x = x;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.y = y;
1056e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
106175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view. If there is not enough room on screen to show
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup in its entirety, this method tries to find a parent scroll
106475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view to scroll. If no parent scroll view can be scrolled, the
106575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * bottom-left corner of the popup is pinned at the top left corner of the
106675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * anchor view.
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor) {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        showAsDropDown(anchor, 0, 0);
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
107775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view offset by the specified x and y coordinates.
107975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
108075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
108175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * scroll view can be scrolled, the bottom-left corner of the popup is
108275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * pinned at the top left corner of the anchor view.
108375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
108475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
108575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
108854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
108954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor, int xoff, int yoff) {
109454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        showAsDropDown(anchor, xoff, yoff, DEFAULT_ANCHORED_GRAVITY);
109554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
109654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
109754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    /**
109875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Displays the content view in a popup window anchored to the corner of
109975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * another view. The window is positioned according to the specified
110075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * gravity and offset by the specified x and y coordinates.
110175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
110275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
110375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
110475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view can be scrolled, the specified vertical gravity will be ignored and
110575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the popup will anchor itself such that it is visible.
110675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
110775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
110875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
110954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
111054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param anchor the view on which to pin the popup window
111154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
111254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
111354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param gravity Alignment of the popup relative to the anchor
111454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
111554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @see #dismiss()
111654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     */
111754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1122e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1123e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
112454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        registerForScrollChanged(anchor, xoff, yoff, gravity);
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = true;
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1132e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff, gravity);
1133e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        updateAboveAnchor(aboveAnchor);
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11383e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    private void updateAboveAnchor(boolean aboveAnchor) {
11393e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        if (aboveAnchor != mAboveAnchor) {
11403e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            mAboveAnchor = aboveAnchor;
11413e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
11423e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            if (mBackground != null) {
11433e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                // If the background drawable provided was a StateListDrawable with above-anchor
11443e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                // and below-anchor states, use those. Otherwise rely on refreshDrawableState to
11453e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                // do the job.
11463e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                if (mAboveAnchorBackgroundDrawable != null) {
11473e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    if (mAboveAnchor) {
11485435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mDecorView.setBackground(mAboveAnchorBackgroundDrawable);
11493e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    } else {
11505435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mDecorView.setBackground(mBelowAnchorBackgroundDrawable);
11513e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    }
11523e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                } else {
11535435a30ae552391f14009c4459731ae149675b18Alan Viverette                    mDecorView.refreshDrawableState();
11543e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                }
11553e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            }
11563e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        }
11573e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    }
11583e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicates whether the popup is showing above (the y coordinate of the popup's bottom
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is less than the y coordinate of the anchor) or below the anchor view (the y coordinate
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the popup is greater than y coordinate of the anchor's bottom).
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The value returned
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by this method is meaningful only after {@link #showAsDropDown(android.view.View)}
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #showAsDropDown(android.view.View, int, int)} was invoked.
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if this popup is showing above the anchor view, false otherwise.
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAboveAnchor() {
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAboveAnchor;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1175e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * Prepare the popup by embedding it into a new ViewGroup if the background
1176e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * drawable is not null. If embedding is required, the layout parameters'
1177e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * height is modified to take into account the background's padding.
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void preparePopup(WindowManager.LayoutParams p) {
1182448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (mContentView == null || mContext == null || mWindowManager == null) {
1183448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            throw new IllegalStateException("You must specify a valid content view by "
1184448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy                    + "calling setContentView() before attempting to show the popup.");
1185448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
1186448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
11878fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // The old decor view may be transitioning out. Make sure it finishes
11888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // and cleans up before we try to create another one.
11898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (mDecorView != null) {
11908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mDecorView.cancelTransitions();
11918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
11928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
11935435a30ae552391f14009c4459731ae149675b18Alan Viverette        // When a background is available, we embed the content view within
11945435a30ae552391f14009c4459731ae149675b18Alan Viverette        // another view that owns the background drawable.
11958fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final View backgroundView;
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
11978fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            backgroundView = createBackgroundView(mContentView);
11988fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            backgroundView.setBackground(mBackground);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12008fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            backgroundView = mContentView;
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1202ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
12038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mDecorView = createDecorView(backgroundView);
12045435a30ae552391f14009c4459731ae149675b18Alan Viverette
12055435a30ae552391f14009c4459731ae149675b18Alan Viverette        // The background owner should be elevated so that it casts a shadow.
12068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        backgroundView.setElevation(mElevation);
12075435a30ae552391f14009c4459731ae149675b18Alan Viverette
12085435a30ae552391f14009c4459731ae149675b18Alan Viverette        // We may wrap that in another view, so we'll need to manually specify
12095435a30ae552391f14009c4459731ae149675b18Alan Viverette        // the surface insets.
12108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final int surfaceInset = (int) Math.ceil(backgroundView.getZ() * 2);
12115435a30ae552391f14009c4459731ae149675b18Alan Viverette        p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
12125435a30ae552391f14009c4459731ae149675b18Alan Viverette        p.hasManualSurfaceInsets = true;
12135435a30ae552391f14009c4459731ae149675b18Alan Viverette
1214b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        mPopupViewInitialLayoutDirectionInherited =
12155435a30ae552391f14009c4459731ae149675b18Alan Viverette                (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPopupWidth = p.width;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPopupHeight = p.height;
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12215435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a PopupViewContainer.
12225435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
12235435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
12245435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a PopupViewContainer that wraps the content view
12255435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
12265435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupBackgroundView createBackgroundView(View contentView) {
12275435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
12285435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
12295435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
12305435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.WRAP_CONTENT;
12315435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
12325435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.MATCH_PARENT;
12335435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
12345435a30ae552391f14009c4459731ae149675b18Alan Viverette
12355435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView backgroundView = new PopupBackgroundView(mContext);
12365435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView.LayoutParams listParams = new PopupBackgroundView.LayoutParams(
12375435a30ae552391f14009c4459731ae149675b18Alan Viverette                ViewGroup.LayoutParams.MATCH_PARENT, height);
12385435a30ae552391f14009c4459731ae149675b18Alan Viverette        backgroundView.addView(contentView, listParams);
12395435a30ae552391f14009c4459731ae149675b18Alan Viverette
12405435a30ae552391f14009c4459731ae149675b18Alan Viverette        return backgroundView;
12415435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
12425435a30ae552391f14009c4459731ae149675b18Alan Viverette
12435435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
12445435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a FrameLayout.
12455435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
12465435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
12475435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a FrameLayout that wraps the content view
12485435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
12495435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView createDecorView(View contentView) {
12505435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
12515435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
12525435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
12535435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.WRAP_CONTENT;
12545435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
12555435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.MATCH_PARENT;
12565435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
12575435a30ae552391f14009c4459731ae149675b18Alan Viverette
12585435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupDecorView decorView = new PopupDecorView(mContext);
12595435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.addView(contentView, ViewGroup.LayoutParams.MATCH_PARENT, height);
12605435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipChildren(false);
12615435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipToPadding(false);
12625435a30ae552391f14009c4459731ae149675b18Alan Viverette
12635435a30ae552391f14009c4459731ae149675b18Alan Viverette        return decorView;
12645435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
12655435a30ae552391f14009c4459731ae149675b18Alan Viverette
12665435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Invoke the popup window by adding the content view to the window
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * manager.</p>
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The content view must be non-null when this method is invoked.</p>
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void invokePopup(WindowManager.LayoutParams p) {
12750c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext != null) {
12760c0b768e1514280812321854db6dfba723c3d169Romain Guy            p.packageName = mContext.getPackageName();
12770c0b768e1514280812321854db6dfba723c3d169Romain Guy        }
12785435a30ae552391f14009c4459731ae149675b18Alan Viverette
12798fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
12808fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.setFitsSystemWindows(mLayoutInsetDecor);
12818fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.requestEnterTransition(mEnterTransition);
12825435a30ae552391f14009c4459731ae149675b18Alan Viverette
12838fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        setLayoutDirectionFromAnchor();
12845435a30ae552391f14009c4459731ae149675b18Alan Viverette
12858fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mWindowManager.addView(decorView, p);
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1288b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private void setLayoutDirectionFromAnchor() {
1289b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        if (mAnchor != null) {
1290b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            View anchor = mAnchor.get();
1291b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
12925435a30ae552391f14009c4459731ae149675b18Alan Viverette                mDecorView.setLayoutDirection(anchor.getLayoutDirection());
1293b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            }
1294b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        }
1295b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    }
1296b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Generate the layout parameters for the popup window.</p>
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param token the window token used to bind the popup's window
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the layout parameters to pass to the window manager
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1304e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette    private WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
1305e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
1306e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1307e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // These gravity settings put the view at the top left corner of the
1308e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // screen. The view is then positioned to the appropriate location by
1309e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // setting the x and y offsets to match the anchor's bottom-left
1310e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // corner.
1311aac0d4ed026d1cfbcf3fa81c6e4eb96f4347ca17Fabrice Di Meglio        p.gravity = Gravity.START | Gravity.TOP;
1312e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.flags = computeFlags(p.flags);
1313e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.type = mWindowLayoutType;
1314e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.token = token;
1315e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.softInputMode = mSoftInputMode;
1316e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.windowAnimations = computeAnimationResource();
1317e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = mBackground.getOpacity();
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = PixelFormat.TRANSLUCENT;
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1323e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1324e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mHeightMode < 0) {
1325e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeightMode;
1326e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1327e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeight;
1328e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1329e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1330e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mWidthMode < 0) {
1331e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidthMode;
1332e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1333e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidth;
1334e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1335e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1336e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Used for debugging.
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return p;
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeFlags(int curFlags) {
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        curFlags &= ~(
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
1349ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
1350ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if(mIgnoreCheekPress) {
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mFocusable) {
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputMethodMode == INPUT_METHOD_NEEDED) {
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mInputMethodMode == INPUT_METHOD_NOT_NEEDED) {
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mTouchable) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1365c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (mOutsideTouchable) {
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mClippingEnabled) {
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
137146e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (isSplitTouchEnabled()) {
137201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown            curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
137301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown        }
1374ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        if (mLayoutInScreen) {
1375ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
1376ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        }
13770bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        if (mLayoutInsetDecor) {
13780bd1d0a15294345bf88b20df28466907f982cec7Adam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
13790bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        }
1380e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        if (mNotTouchModal) {
1381e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
1382e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        }
1383393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mAttachedInDecor) {
1384393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale          curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
1385393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return curFlags;
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1388393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeAnimationResource() {
13905435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (mAnimationStyle == ANIMATION_STYLE_DEFAULT) {
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsDropdown) {
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mAboveAnchor
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ? com.android.internal.R.style.Animation_DropDownUp
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : com.android.internal.R.style.Animation_DropDownDown;
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1400560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1402560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * Positions the popup window on screen. When the popup window is too tall
1403560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to fit under the anchor, a parent scroll view is seeked and scrolled up
1404560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to reclaim space. If scrolling is not possible or not enough, the popup
1405560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * window gets moved on top of the anchor.
1406560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * <p>
1407560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * The height must have been set on the layout parameters prior to calling
1408560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * this method.
14095435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which the popup window must be anchored
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters used to display the drop down
1412560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param xoff horizontal offset used to adjust for background padding
1413560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param yoff vertical offset used to adjust for background padding
1414560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param gravity horizontal gravity specifying popup alignment
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is translated upwards to fit on screen
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1417560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff,
1418560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            int yoff, int gravity) {
141962e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        final int anchorHeight = anchor.getHeight();
1420560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int anchorWidth = anchor.getWidth();
1421560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        if (mOverlapAnchor) {
1422560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            yoff -= anchorHeight;
1423560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        }
1424560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationInWindow(mDrawingLocation);
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.x = mDrawingLocation[0] + xoff;
142762e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        p.y = mDrawingLocation[1] + anchorHeight + yoff;
142854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1429560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
1430560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                & Gravity.HORIZONTAL_GRAVITY_MASK;
143154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        if (hgrav == Gravity.RIGHT) {
1432560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Flip the location to align the right sides of the popup and
1433560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // anchor instead of left.
1434560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            p.x -= mPopupWidth - anchorWidth;
143554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        }
1436560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean onTop = false;
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
143954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        p.gravity = Gravity.LEFT | Gravity.TOP;
144054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationOnScreen(mScreenLocation);
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect displayFrame = new Rect();
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getWindowVisibleDisplayFrame(displayFrame);
144462e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell
1445560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int screenY = mScreenLocation[1] + anchorHeight + yoff;
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View root = anchor.getRootView();
1447560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        if (screenY + mPopupHeight > displayFrame.bottom
1448560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                || p.x + mPopupWidth - root.getWidth() > 0) {
1449560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // If the drop down disappears at the bottom of the screen, we try
1450560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // to scroll a parent scrollview or move the drop down back up on
1451560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // top of the edit box.
1452b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell            if (mAllowScrollingAnchorParent) {
1453560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final int scrollX = anchor.getScrollX();
1454560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final int scrollY = anchor.getScrollY();
1455560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
1456560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                        scrollY + mPopupHeight + anchorHeight + yoff);
1457b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell                anchor.requestRectangleOnScreen(r, true);
1458b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell            }
14593e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
1460560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Now we re-evaluate the space available, and decide from that
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // whether the pop-up will go above or below the anchor.
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            anchor.getLocationInWindow(mDrawingLocation);
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.x = mDrawingLocation[0] + xoff;
1464560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            p.y = mDrawingLocation[1] + anchorHeight + yoff;
146554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1466560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Preserve the gravity adjustment.
146754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            if (hgrav == Gravity.RIGHT) {
1468560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                p.x -= mPopupWidth - anchorWidth;
146954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            }
1470560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1471560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Determine whether there is more space above or below the anchor.
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            anchor.getLocationOnScreen(mScreenLocation);
1473560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            onTop = (displayFrame.bottom - mScreenLocation[1] - anchorHeight - yoff) <
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    (mScreenLocation[1] - yoff - displayFrame.top);
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (onTop) {
147654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell                p.gravity = Gravity.LEFT | Gravity.BOTTOM;
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.y = root.getHeight() - mDrawingLocation[1] + yoff;
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1479560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                p.y = mDrawingLocation[1] + anchorHeight + yoff;
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
148356c2d337e02a275397fc9d0460dca90977f199acAdam Powell        if (mClipToScreen) {
148456c2d337e02a275397fc9d0460dca90977f199acAdam Powell            final int displayFrameWidth = displayFrame.right - displayFrame.left;
1485560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            final int right = p.x + p.width;
148656c2d337e02a275397fc9d0460dca90977f199acAdam Powell            if (right > displayFrameWidth) {
148756c2d337e02a275397fc9d0460dca90977f199acAdam Powell                p.x -= right - displayFrameWidth;
148856c2d337e02a275397fc9d0460dca90977f199acAdam Powell            }
1489560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
149056c2d337e02a275397fc9d0460dca90977f199acAdam Powell            if (p.x < displayFrame.left) {
149156c2d337e02a275397fc9d0460dca90977f199acAdam Powell                p.x = displayFrame.left;
149256c2d337e02a275397fc9d0460dca90977f199acAdam Powell                p.width = Math.min(p.width, displayFrameWidth);
149356c2d337e02a275397fc9d0460dca90977f199acAdam Powell            }
149456c2d337e02a275397fc9d0460dca90977f199acAdam Powell
14955f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            if (onTop) {
1496560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
14975f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell                if (popupTop < 0) {
14985f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell                    p.y += popupTop;
14995f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell                }
15005f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            } else {
15015f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell                p.y = Math.max(p.y, displayFrame.top);
15025f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            }
150356c2d337e02a275397fc9d0460dca90977f199acAdam Powell        }
150456c2d337e02a275397fc9d0460dca90977f199acAdam Powell
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
1506560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return onTop;
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15095435a30ae552391f14009c4459731ae149675b18Alan Viverette
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
15155435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMaxAvailableHeight(View anchor) {
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getMaxAvailableHeight(anchor, 0);
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yOffset y offset from the view's bottom edge
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMaxAvailableHeight(View anchor, int yOffset) {
153698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        return getMaxAvailableHeight(anchor, yOffset, false);
153798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    }
15385435a30ae552391f14009c4459731ae149675b18Alan Viverette
153998acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    /**
154098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * Returns the maximum height that is available for the popup to be
154198acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * completely shown, optionally ignoring any bottom decorations such as
154298acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the input method. It is recommended that this height be the maximum for
154398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the popup's height, otherwise it is possible that the popup will be
154498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * clipped.
15455435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
154698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param anchor The view on which the popup window must be anchored.
154798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param yOffset y offset from the view's bottom edge
154898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param ignoreBottomDecorations if true, the height returned will be
154998acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        all the way to the bottom of the display, ignoring any
155098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        bottom decorations
155198acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @return The maximum available height for the popup to be completely
155298acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *         shown.
15535435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
155498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @hide Pending API council approval.
155598acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     */
155698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    public int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) {
15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect displayFrame = new Rect();
15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getWindowVisibleDisplayFrame(displayFrame);
15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int[] anchorPos = mDrawingLocation;
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationOnScreen(anchorPos);
15625435a30ae552391f14009c4459731ae149675b18Alan Viverette
156398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        int bottomEdge = displayFrame.bottom;
156498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        if (ignoreBottomDecorations) {
1565a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powell            Resources res = anchor.getContext().getResources();
15663f4a764cf400aa209c1f8f76a1c73143eefc4905Adam Powell            bottomEdge = res.getDisplayMetrics().heightPixels;
156798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        }
156898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // anchorPos[1] is distance from anchor to top of screen
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int returnedHeight = Math.max(distanceToBottom, distanceToTop);
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBackground.getPadding(mTempRect);
15755435a30ae552391f14009c4459731ae149675b18Alan Viverette            returnedHeight -= mTempRect.top + mTempRect.bottom;
15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15775435a30ae552391f14009c4459731ae149675b18Alan Viverette
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return returnedHeight;
15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15805435a30ae552391f14009c4459731ae149675b18Alan Viverette
15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15827878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * Disposes of the popup window. This method can be invoked only after
15837878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * {@link #showAsDropDown(android.view.View)} has been executed. Failing
15847878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * that, calling this method will have no effect.
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
15865435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #showAsDropDown(android.view.View)
15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dismiss() {
15898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (!isShowing() || mIsTransitioningToDismiss) {
1590e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            return;
1591e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
159206f938e8aa56cd89ab0bdb04c8b946392c428dd1Svetoslav Ganov
15938fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
15948fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final View contentView = mContentView;
15958fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
15968fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewGroup contentHolder;
15978fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewParent contentParent = contentView.getParent();
15988fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentParent instanceof ViewGroup) {
15998fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = ((ViewGroup) contentParent);
16008fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        } else {
16018fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = null;
16028fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
16038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
16048fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // Ensure any ongoing or pending transitions are canceled.
16058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.cancelTransitions();
16068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
1607e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        unregisterForScrollChanged();
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        mIsShowing = false;
16108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = true;
1611b82d074038f4c8d86e1bd4f3fa4d3780bd4bcba5Craig Mautner
16128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (mExitTransition != null && decorView.isLaidOut()) {
16138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            decorView.startExitTransition(mExitTransition, new TransitionListenerAdapter() {
1614e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette                @Override
1615e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette                public void onTransitionEnd(Transition transition) {
16168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    dismissImmediate(decorView, contentHolder, contentView);
1617e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette                }
1618e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            });
1619e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
16208fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            dismissImmediate(decorView, contentHolder, contentView);
16217878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette        }
16227878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
16237878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette        if (mOnDismissListener != null) {
16247878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette            mOnDismissListener.onDismiss();
16255435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
16265435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
16275435a30ae552391f14009c4459731ae149675b18Alan Viverette
16285435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
16295435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Removes the popup from the window manager and tears down the supporting
16305435a30ae552391f14009c4459731ae149675b18Alan Viverette     * view hierarchy, if necessary.
16315435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
16328fd949e680c15d397084430d4907c16cedfacddaAlan Viverette    private void dismissImmediate(View decorView, ViewGroup contentHolder, View contentView) {
16338fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // If this method gets called and the decor view doesn't have a parent,
16348fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // then it was either never added or was already removed. That should
16358fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // never happen, but it's worth checking to avoid potential crashes.
16368fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (decorView.getParent() != null) {
16378fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mWindowManager.removeViewImmediate(decorView);
1638df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette        }
1639df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette
16408fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentHolder != null) {
16418fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder.removeView(contentView);
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16438fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
16448fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // This needs to stay until after all transitions have ended since we
16458fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // need the reference to cancel transitions in preparePopup().
16468fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mDecorView = null;
16478fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = false;
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the listener to be called when the window is dismissed.
16525435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param onDismissListener The listener.
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnDismissListener(OnDismissListener onDismissListener) {
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnDismissListener = onDismissListener;
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16585435a30ae552391f14009c4459731ae149675b18Alan Viverette
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Updates the state of the popup window, if it is currently being displayed,
1661259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * from the currently set state.
1662259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1663259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * This includes:
1664259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <ul>
1665259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setClippingEnabled(boolean)}</li>
1666259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setFocusable(boolean)}</li>
1667259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setIgnoreCheekPress()}</li>
1668259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setInputMethodMode(int)}</li>
1669259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setTouchable(boolean)}</li>
1670259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setAnimationStyle(int)}</li>
1671259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * </ul>
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update() {
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16775435a30ae552391f14009c4459731ae149675b18Alan Viverette
16785435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
16795435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
16805435a30ae552391f14009c4459731ae149675b18Alan Viverette
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = false;
16825435a30ae552391f14009c4459731ae149675b18Alan Viverette
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1694b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
1696b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
16975435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1700d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy
1701d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    /**
1702259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the dimension of the popup window.
1703259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1704259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
1705259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
1706d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     *
1707259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1708259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
1709d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     */
1710d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    public void update(int width, int height) {
17115435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
17125435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
1713d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy        update(p.x, p.y, width, height, false);
1714d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    }
17155435a30ae552391f14009c4459731ae149675b18Alan Viverette
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1717259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1718259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1719259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1720259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1721259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
1725259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1726259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height) {
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        update(x, y, width, height, false);
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1733259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1734259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1735259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1736259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1737259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
1741259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1742259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
1743259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param force {@code true} to reposition the window even if the specified
1744259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              position already seems to correspond to the LayoutParams,
1745259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              {@code false} to only reposition if needed
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height, boolean force) {
1748259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (width >= 0) {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastWidth = width;
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setWidth(width);
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1753259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (height >= 0) {
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastHeight = height;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setHeight(height);
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17625435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
17635435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = force;
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width != -1 && p.width != finalWidth) {
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.width = mLastWidth = finalWidth;
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (height != -1 && p.height != finalHeight) {
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.height = mLastHeight = finalHeight;
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.x != x) {
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.x = x;
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.y != y) {
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.y = y;
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
180098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
1802b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
18035435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1808259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1809259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1810259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
1811259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
1814259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1815259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int width, int height) {
181875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        update(anchor, false, 0, 0, true, width, height);
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1822259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1823259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1824259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1825259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1826259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
1827259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1828259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the view later scrolls to move {@code anchor} to a different
1829259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * location, the popup will be moved correspondingly.
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param xoff x offset from the view's left edge
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yoff y offset from the view's bottom edge
1834259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1835259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int xoff, int yoff, int width, int height) {
183875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        update(anchor, true, xoff, yoff, true, width, height);
1839105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
1840105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
1841105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private void update(View anchor, boolean updateLocation, int xoff, int yoff,
184275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette            boolean updateDimension, int width, int height) {
1843105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
184875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final WeakReference<View> oldAnchor = mAnchor;
184975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
185081f08086b44a117097960195d2c9072e29644962Gilles Debunne        if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
185175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette            registerForScrollChanged(anchor, xoff, yoff, mAnchoredGravity);
185281f08086b44a117097960195d2c9072e29644962Gilles Debunne        } else if (needsUpdate) {
185381f08086b44a117097960195d2c9072e29644962Gilles Debunne            // No need to register again if this is a DropDown, showAsDropDown already did.
185481f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorXoff = xoff;
185581f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorYoff = yoff;
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1858105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (updateDimension) {
1859105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (width == -1) {
1860105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                width = mPopupWidth;
1861105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
1862105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mPopupWidth = width;
1863105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
1864105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (height == -1) {
1865105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                height = mPopupHeight;
1866105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
1867105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mPopupHeight = height;
1868105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1870105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
187175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final WindowManager.LayoutParams p =
18725435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
187375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final int x = p.x;
187475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final int y = p.y;
1875105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (updateLocation) {
187675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette            updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, mAnchoredGravity));
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
187854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
187954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell                    mAnchoredGravity));
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1881b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
18823e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        update(p.x, p.y, width, height, x != p.x || y != p.y);
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Listener that is called when this popup window is dismissed.
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnDismissListener {
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when this popup window is dismissed.
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onDismiss();
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void unregisterForScrollChanged() {
1896e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WeakReference<View> anchorRef = mAnchor;
1897e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final View anchor = anchorRef == null ? null : anchorRef.get();
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchor != null) {
1899e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            final ViewTreeObserver vto = anchor.getViewTreeObserver();
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.removeOnScrollChangedListener(mOnScrollChangedListener);
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1902e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchor = null;
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
190654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private void registerForScrollChanged(View anchor, int xoff, int yoff, int gravity) {
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        unregisterForScrollChanged();
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19095435a30ae552391f14009c4459731ae149675b18Alan Viverette        mAnchor = new WeakReference<>(anchor);
1910e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1911e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final ViewTreeObserver vto = anchor.getViewTreeObserver();
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vto != null) {
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.addOnScrollChangedListener(mOnScrollChangedListener);
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorXoff = xoff;
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorYoff = yoff;
191854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mAnchoredGravity = gravity;
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19215435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupDecorView extends FrameLayout {
19228fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private TransitionListenerAdapter mPendingExitListener;
19238fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
19245435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupDecorView(Context context) {
19255435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
19265435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchKeyEvent(KeyEvent event) {
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
19314ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                if (getKeyDispatcherState() == null) {
19324ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                    return super.dispatchKeyEvent(event);
19334ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                }
19344ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson
19355435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
19365435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
1937b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null) {
1938b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        state.startTracking(event, this);
1939b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
19408d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    return true;
1941b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                } else if (event.getAction() == KeyEvent.ACTION_UP) {
19425435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
1943b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null && state.isTracking(event) && !event.isCanceled()) {
1944b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        dismiss();
1945b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        return true;
1946b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
19478d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                }
19488d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                return super.dispatchKeyEvent(event);
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.dispatchKeyEvent(event);
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchTouchEvent(MotionEvent ev) {
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.dispatchTouchEvent(ev);
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onTouchEvent(MotionEvent event) {
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int x = (int) event.getX();
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int y = (int) event.getY();
19665435a30ae552391f14009c4459731ae149675b18Alan Viverette
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((event.getAction() == MotionEvent.ACTION_DOWN)
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.onTouchEvent(event);
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19788fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
19798fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
19808fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Requests that an enter transition run after the next layout pass.
19818fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
19828fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void requestEnterTransition(Transition transition) {
19838fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final ViewTreeObserver observer = getViewTreeObserver();
19848fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (observer != null && transition != null) {
19858fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final Transition enterTransition = transition.clone();
19868fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
19878fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                // Postpone the enter transition after the first layout pass.
19888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
19898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    @Override
19908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    public void onGlobalLayout() {
19918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        final ViewTreeObserver observer = getViewTreeObserver();
19928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        if (observer != null) {
19938fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                            observer.removeOnGlobalLayoutListener(this);
19948fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        }
19958fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
19968fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        startEnterTransition(enterTransition);
19978fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    }
19988fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                });
19998fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20008fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
20018fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20028fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
20038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts the pending enter transition, if one is set.
20048fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
20058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private void startEnterTransition(Transition enterTransition) {
20068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
20078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
20088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
20098fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                enterTransition.addTarget(child);
20108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
20118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, enterTransition);
20148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
20168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
20178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.VISIBLE);
20188fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20198fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
20208fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20218fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
20228fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts an exit transition immediately.
20238fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <p>
20248fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <strong>Note:</strong> The transition listener is guaranteed to have
20258fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * its {@code onTransitionEnd} method called even if the transition
20268fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * never starts; however, it may be called with a {@code null} argument.
20278fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
20288fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void startExitTransition(Transition transition, final TransitionListener listener) {
20298fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (transition == null) {
20308fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                return;
20318fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20328fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20338fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // The exit listener MUST be called for cleanup, even if the
20348fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // transition never starts or ends. Stash it for later.
20358fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mPendingExitListener = new TransitionListenerAdapter() {
20368fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                @Override
20378fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                public void onTransitionEnd(Transition transition) {
20388fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    listener.onTransitionEnd(transition);
20398fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20408fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    // The listener was called. Our job here is done.
20418fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    mPendingExitListener = null;
20428fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                }
20438fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            };
20448fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20458fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final Transition exitTransition = transition.clone();
20468fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            exitTransition.addListener(mPendingExitListener);
20478fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20488fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
20498fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
20508fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
20518fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                exitTransition.addTarget(child);
20528fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20538fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20548fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, exitTransition);
20558fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20568fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
20578fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
20588fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
20598fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20608fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
20618fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20628fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
20638fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Cancels all pending or current transitions.
20648fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
20658fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void cancelTransitions() {
20668fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.endTransitions(this);
20678fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
20688fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (mPendingExitListener != null) {
20698fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                mPendingExitListener.onTransitionEnd(null);
20708fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
20718fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
20725435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
20735435a30ae552391f14009c4459731ae149675b18Alan Viverette
20745435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupBackgroundView extends FrameLayout {
20755435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupBackgroundView(Context context) {
20765435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
20775435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
207875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
207975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        @Override
20805435a30ae552391f14009c4459731ae149675b18Alan Viverette        protected int[] onCreateDrawableState(int extraSpace) {
20815435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (mAboveAnchor) {
20825435a30ae552391f14009c4459731ae149675b18Alan Viverette                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
20835435a30ae552391f14009c4459731ae149675b18Alan Viverette                View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
20845435a30ae552391f14009c4459731ae149675b18Alan Viverette                return drawableState;
208575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            } else {
20865435a30ae552391f14009c4459731ae149675b18Alan Viverette                return super.onCreateDrawableState(extraSpace);
208775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
208875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2091