PopupWindow.java revision 1e940dc2d165fa6cdedb6945811988502f87ddce
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
21b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viveretteimport android.annotation.NonNull;
221e940dc2d165fa6cdedb6945811988502f87ddceAlan Viveretteimport android.annotation.Nullable;
2375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.Context;
2475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.res.TypedArray;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.StateListDrawable;
2946e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brownimport android.os.Build;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
315435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.Transition;
325435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.Transition.EpicenterCallback;
338fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.transition.Transition.TransitionListener;
348fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.transition.Transition.TransitionListenerAdapter;
355435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionInflater;
365435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionManager;
375435a30ae552391f14009c4459731ae149675b18Alan Viveretteimport android.transition.TransitionSet;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
39c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.Gravity;
40c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.KeyEvent;
41c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.MotionEvent;
42c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View;
43634a808226cc5d00bd6897bdc881cafe064e37acAlan Viveretteimport android.view.View.OnAttachStateChangeListener;
44a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport android.view.View.OnTouchListener;
45c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewGroup;
468fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.view.ViewParent;
47c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewTreeObserver;
488fd949e680c15d397084430d4907c16cedfacddaAlan Viveretteimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
49c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.ViewTreeObserver.OnScrollChangedListener;
50a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport android.view.WindowManager;
51259c2840691a79634ffd8f63291ec21c21819542Alan Viveretteimport android.view.WindowManager.LayoutParams;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
53a7287f4d199b5d86e01d1de9d9a9db7e3221b02dAdam Powellimport java.lang.ref.WeakReference;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
551e940dc2d165fa6cdedb6945811988502f87ddceAlan Viveretteimport static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
561e940dc2d165fa6cdedb6945811988502f87ddceAlan Viveretteimport static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
571e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
591e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
601e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * This class represents a popup window that can be used to display an
611e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * arbitrary view. The popup window is a floating container that appears on top
621e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * of the current activity.
631e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
641e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <a name="Animation"></a>
651e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <h3>Animation</h3>
661e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
671e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * On all versions of Android, popup window enter and exit animations may be
681e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * specified by calling {@link #setAnimationStyle(int)} and passing the
691e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * resource ID for an animation style that defines {@code windowEnterAnimation}
701e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * and {@code windowExitAnimation}. For example, passing
711e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * {@link android.R.style#Animation_Dialog} will give a scale and alpha
721e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * animation.
731e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </br>
741e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * A window animation style may also be specified in the popup window's style
751e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * XML via the {@link android.R.styleable#PopupWindow_popupAnimationStyle popupAnimationStyle}
761e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * attribute.
771e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
781e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
791e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * Starting with API 23, more complex popup window enter and exit transitions
801e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * may be specified by calling either {@link #setEnterTransition(Transition)}
811e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * or {@link #setExitTransition(Transition)} and passing a  {@link Transition}.
821e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </br>
831e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * Popup enter and exit transitions may also be specified in the popup window's
841e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * style XML via the {@link android.R.styleable#PopupWindow_popupEnterTransition popupEnterTransition}
851e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * and {@link android.R.styleable#PopupWindow_popupExitTransition popupExitTransition}
861e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * attributes, respectively.
871e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
881e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette *
891e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_overlapAnchor
901e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupAnimationStyle
911e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupBackground
921e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupElevation
931e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
941e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupExitTransition
955435a30ae552391f14009c4459731ae149675b18Alan Viverette *
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.AutoCompleteTextView
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.Spinner
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PopupWindow {
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
101e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method should be based on the focusability of the popup.  That is
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if it is focusable than it needs to work with the input method, else
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it doesn't.
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
1075435a30ae552391f14009c4459731ae149675b18Alan Viverette
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
109e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed so that the user can also operate
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the input method while it is shown.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NEEDED = 1;
1155435a30ae552391f14009c4459731ae149675b18Alan Viverette
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
117e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed to use as much space on the
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen as needed, regardless of whether this covers the input method.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NOT_NEEDED = 2;
12354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
12454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private static final int DEFAULT_ANCHORED_GRAVITY = Gravity.TOP | Gravity.START;
12554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1265435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
1275435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Default animation style indicating that separate animations should be
1285435a30ae552391f14009c4459731ae149675b18Alan Viverette     * used for top/bottom anchoring states.
1295435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
1305435a30ae552391f14009c4459731ae149675b18Alan Viverette    private static final int ANIMATION_STYLE_DEFAULT = -1;
1315435a30ae552391f14009c4459731ae149675b18Alan Viverette
1325435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final int[] mDrawingLocation = new int[2];
1335435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final int[] mScreenLocation = new int[2];
1345435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final Rect mTempRect = new Rect();
1355435a30ae552391f14009c4459731ae149675b18Alan Viverette
136448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private Context mContext;
137448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private WindowManager mWindowManager;
1385435a30ae552391f14009c4459731ae149675b18Alan Viverette
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsShowing;
1408fd949e680c15d397084430d4907c16cedfacddaAlan Viverette    private boolean mIsTransitioningToDismiss;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsDropdown;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1435435a30ae552391f14009c4459731ae149675b18Alan Viverette    /** View that handles event dispatch and content transitions. */
1445435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView mDecorView;
1455435a30ae552391f14009c4459731ae149675b18Alan Viverette
146697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    /** View that holds the background and may animate during a transition. */
147697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    private View mBackgroundView;
148697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette
149697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    /** The contents of the popup. May be identical to the background view. */
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mContentView;
1515435a30ae552391f14009c4459731ae149675b18Alan Viverette
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFocusable;
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
1547eab094722af54717859b7dcce3cc050f059e00bDianne Hackborn    private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mTouchable = true;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOutsideTouchable = false;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mClippingEnabled = true;
15846e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown    private int mSplitTouchEnabled = -1;
159ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    private boolean mLayoutInScreen;
16056c2d337e02a275397fc9d0460dca90977f199acAdam Powell    private boolean mClipToScreen;
161348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    private boolean mAllowScrollingAnchorParent = true;
1620bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    private boolean mLayoutInsetDecor = false;
163e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    private boolean mNotTouchModal;
164393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecor = true;
165393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecorSet = false;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnTouchListener mTouchInterceptor;
168393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mWidthMode;
170259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mWidth = LayoutParams.WRAP_CONTENT;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastWidth;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mHeightMode;
173259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mHeight = LayoutParams.WRAP_CONTENT;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastHeight;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPopupWidth;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mPopupHeight;
17856c2d337e02a275397fc9d0460dca90977f199acAdam Powell
179ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    private float mElevation;
180ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBackground;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mAboveAnchorBackgroundDrawable;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBelowAnchorBackgroundDrawable;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1855435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mEnterTransition;
1865435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mExitTransition;
18791098574f90277128415e9593cce1e495cc51465Alan Viverette    private Rect mEpicenterBounds;
188560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAboveAnchor;
190574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
1915435a30ae552391f14009c4459731ae149675b18Alan Viverette
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnDismissListener mOnDismissListener;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIgnoreCheekPress = false;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1955435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
1965435a30ae552391f14009c4459731ae149675b18Alan Viverette
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.attr.state_above_anchor
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
201634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
202634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            new OnAttachStateChangeListener() {
203634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                @Override
204634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                public void onViewAttachedToWindow(View v) {}
205634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
206634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                @Override
207634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                public void onViewDetachedFromWindow(View v) {
208634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    mIsAnchorRootAttached = false;
209634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                }
210634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            };
211634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WeakReference<View> mAnchor;
213634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private WeakReference<View> mAnchorRoot;
214634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private boolean mIsAnchorRootAttached;
215560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
2165435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
2175435a30ae552391f14009c4459731ae149675b18Alan Viverette        @Override
2185435a30ae552391f14009c4459731ae149675b18Alan Viverette        public void onScrollChanged() {
2195435a30ae552391f14009c4459731ae149675b18Alan Viverette            final View anchor = mAnchor != null ? mAnchor.get() : null;
2205435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (anchor != null && mDecorView != null) {
2215435a30ae552391f14009c4459731ae149675b18Alan Viverette                final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
2225435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mDecorView.getLayoutParams();
2235435a30ae552391f14009c4459731ae149675b18Alan Viverette
2245435a30ae552391f14009c4459731ae149675b18Alan Viverette                updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
2255435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mAnchoredGravity));
2265435a30ae552391f14009c4459731ae149675b18Alan Viverette                update(p.x, p.y, -1, -1, true);
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2285435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2295435a30ae552391f14009c4459731ae149675b18Alan Viverette    };
230560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
2315435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorXoff;
2325435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorYoff;
2335435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchoredGravity;
234560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette    private boolean mOverlapAnchor;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
236b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private boolean mPopupViewInitialLayoutDirectionInherited;
237b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context) {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, null);
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context, AttributeSet attrs) {
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, attrs, com.android.internal.R.attr.popupWindowStyle);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
261617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
262617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
263c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
2645435a30ae552391f14009c4459731ae149675b18Alan Viverette
265c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
266c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Create a new, empty, non focusable popup window of dimension (0,0).</p>
2675435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
268c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>The popup does not provide a background.</p>
269c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
270c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
27275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
274617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(
275ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                attrs, R.styleable.PopupWindow, defStyleAttr, defStyleRes);
276ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        final Drawable bg = a.getDrawable(R.styleable.PopupWindow_popupBackground);
277ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = a.getDimension(R.styleable.PopupWindow_popupElevation, 0);
278560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
279c3808b5dc7d5873d04e8a0a247b179b2757764baAdam Powell
2805435a30ae552391f14009c4459731ae149675b18Alan Viverette        // Preserve default behavior from Gingerbread. If the animation is
2815435a30ae552391f14009c4459731ae149675b18Alan Viverette        // undefined or explicitly specifies the Gingerbread animation style,
2825435a30ae552391f14009c4459731ae149675b18Alan Viverette        // use a sentinel value.
2835435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupAnimationStyle)) {
2845435a30ae552391f14009c4459731ae149675b18Alan Viverette            final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, 0);
2855435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (animStyle == R.style.Animation_PopupWindow) {
2865435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2875435a30ae552391f14009c4459731ae149675b18Alan Viverette            } else {
2885435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = animStyle;
2895435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
2905435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
2915435a30ae552391f14009c4459731ae149675b18Alan Viverette            mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2925435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2935435a30ae552391f14009c4459731ae149675b18Alan Viverette
2945435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition enterTransition = getTransition(a.getResourceId(
2955435a30ae552391f14009c4459731ae149675b18Alan Viverette                R.styleable.PopupWindow_popupEnterTransition, 0));
2965435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition exitTransition;
2975435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupExitTransition)) {
2985435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = getTransition(a.getResourceId(
2995435a30ae552391f14009c4459731ae149675b18Alan Viverette                    R.styleable.PopupWindow_popupExitTransition, 0));
3005435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
3015435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = enterTransition == null ? null : enterTransition.clone();
3025435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
305ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
3065435a30ae552391f14009c4459731ae149675b18Alan Viverette        setEnterTransition(enterTransition);
3075435a30ae552391f14009c4459731ae149675b18Alan Viverette        setExitTransition(exitTransition);
308ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        setBackgroundDrawable(bg);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow() {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, 0, 0);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window are (0,0).</p>
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, 0, 0);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window. The dimension of the
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window must be passed to this constructor.</p>
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(int width, int height) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, width, height);
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window must be passed to
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this constructor.</p>
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView, int width, int height) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, width, height, false);
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new popup window which can display the <tt>contentView</tt>.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The dimension of the window must be passed to this constructor.</p>
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup can be focused, false otherwise
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
376448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    public PopupWindow(View contentView, int width, int height, boolean focusable) {
377448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (contentView != null) {
378448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = contentView.getContext();
379448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
380448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
381393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setContentView(contentView);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setWidth(width);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeight(height);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusable(focusable);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3881e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
3891e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Sets the enter transition to be used when the popup window is shown.
3901e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
3911e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @param enterTransition the enter transition, or {@code null} to clear
3921e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #getEnterTransition()
3931e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
3941e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
3951e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public void setEnterTransition(@Nullable Transition enterTransition) {
3965435a30ae552391f14009c4459731ae149675b18Alan Viverette        mEnterTransition = enterTransition;
3975435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
3985435a30ae552391f14009c4459731ae149675b18Alan Viverette
3991e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
4001e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Returns the enter transition to be used when the popup window is shown.
4011e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4021e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @return the enter transition, or {@code null} if not set
4031e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #setEnterTransition(Transition)
4041e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
4051e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4061e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    @Nullable
4071e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public Transition getEnterTransition() {
4081e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette        return mEnterTransition;
4091e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    }
4101e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
4111e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
4121e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Sets the exit transition to be used when the popup window is dismissed.
4131e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4141e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @param exitTransition the exit transition, or {@code null} to clear
4151e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #getExitTransition()
4161e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
4171e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4181e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public void setExitTransition(@Nullable Transition exitTransition) {
4195435a30ae552391f14009c4459731ae149675b18Alan Viverette        mExitTransition = exitTransition;
4205435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
4215435a30ae552391f14009c4459731ae149675b18Alan Viverette
42291098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
4231e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Returns the exit transition to be used when the popup window is
4241e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * dismissed.
4251e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4261e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @return the exit transition, or {@code null} if not set
4271e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #setExitTransition(Transition)
4281e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
4291e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4301e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    @Nullable
4311e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public Transition getExitTransition() {
4321e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette        return mExitTransition;
4331e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    }
4341e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
4351e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
43691098574f90277128415e9593cce1e495cc51465Alan Viverette     * Sets the bounds used as the epicenter of the enter and exit transitions.
43791098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
43891098574f90277128415e9593cce1e495cc51465Alan Viverette     * Transitions use a point or Rect, referred to as the epicenter, to orient
43991098574f90277128415e9593cce1e495cc51465Alan Viverette     * the direction of travel. For popup windows, the anchor view bounds are
44091098574f90277128415e9593cce1e495cc51465Alan Viverette     * used as the default epicenter.
44191098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
44291098574f90277128415e9593cce1e495cc51465Alan Viverette     * See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
44391098574f90277128415e9593cce1e495cc51465Alan Viverette     * information about how transition epicenters.
44491098574f90277128415e9593cce1e495cc51465Alan Viverette     *
44591098574f90277128415e9593cce1e495cc51465Alan Viverette     * @param bounds the epicenter bounds relative to the anchor view, or
44691098574f90277128415e9593cce1e495cc51465Alan Viverette     *               {@code null} to use the default epicenter
44791098574f90277128415e9593cce1e495cc51465Alan Viverette     * @see #getTransitionEpicenter()
44891098574f90277128415e9593cce1e495cc51465Alan Viverette     * @hide
44991098574f90277128415e9593cce1e495cc51465Alan Viverette     */
45091098574f90277128415e9593cce1e495cc51465Alan Viverette    public void setEpicenterBounds(Rect bounds) {
45191098574f90277128415e9593cce1e495cc51465Alan Viverette        mEpicenterBounds = bounds;
45291098574f90277128415e9593cce1e495cc51465Alan Viverette    }
45391098574f90277128415e9593cce1e495cc51465Alan Viverette
4545435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition getTransition(int resId) {
4555435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (resId != 0 && resId != R.transition.no_transition) {
4565435a30ae552391f14009c4459731ae149675b18Alan Viverette            final TransitionInflater inflater = TransitionInflater.from(mContext);
4575435a30ae552391f14009c4459731ae149675b18Alan Viverette            final Transition transition = inflater.inflateTransition(resId);
4585435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (transition != null) {
4595435a30ae552391f14009c4459731ae149675b18Alan Viverette                final boolean isEmpty = transition instanceof TransitionSet
4605435a30ae552391f14009c4459731ae149675b18Alan Viverette                        && ((TransitionSet) transition).getTransitionCount() == 0;
4615435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (!isEmpty) {
4625435a30ae552391f14009c4459731ae149675b18Alan Viverette                    return transition;
4635435a30ae552391f14009c4459731ae149675b18Alan Viverette                }
4645435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
4655435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
4665435a30ae552391f14009c4459731ae149675b18Alan Viverette        return null;
4675435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
4685435a30ae552391f14009c4459731ae149675b18Alan Viverette
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
470ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Return the drawable used as the popup window's background.
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
472ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the background drawable or {@code null} if not set
473ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setBackgroundDrawable(Drawable)
474ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getBackground() {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBackground;
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
481ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the background drawable for this popup window. The background
482ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * can be set to {@code null}.
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param background the popup's background
485ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getBackground()
486ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setBackgroundDrawable(Drawable background) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBackground = background;
490ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
491ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // If this is a StateListDrawable, try to find and store the drawable to be
492ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed above its anchor view, and the one to be
493ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed below its anchor view. We extract
494ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // the drawables ourselves to work around a problem with using refreshDrawableState
495ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // that it will take into account the padding of all drawables specified in a
496ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // StateListDrawable, thus adding superfluous padding to drop-down views.
497ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        //
498ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // We assume a StateListDrawable will have a drawable for ABOVE_ANCHOR_STATE_SET and
499ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // at least one other drawable, intended for the 'below-anchor state'.
500ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        if (mBackground instanceof StateListDrawable) {
501ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            StateListDrawable stateList = (StateListDrawable) mBackground;
502ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
503ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Find the above-anchor view - this one's easy, it should be labeled as such.
504ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int aboveAnchorStateIndex = stateList.getStateDrawableIndex(ABOVE_ANCHOR_STATE_SET);
505ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
506ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Now, for the below-anchor view, look for any other drawable specified in the
507ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // StateListDrawable which is not for the above-anchor state and use that.
508ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int count = stateList.getStateCount();
509ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int belowAnchorStateIndex = -1;
510ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            for (int i = 0; i < count; i++) {
511ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                if (i != aboveAnchorStateIndex) {
512ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    belowAnchorStateIndex = i;
513ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    break;
514ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                }
515ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
516ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
517ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Store the drawables we found, if we found them. Otherwise, set them both
518ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // to null so that we'll just use refreshDrawableState.
519ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            if (aboveAnchorStateIndex != -1 && belowAnchorStateIndex != -1) {
520ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = stateList.getStateDrawable(aboveAnchorStateIndex);
521ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = stateList.getStateDrawable(belowAnchorStateIndex);
522ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            } else {
523ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = null;
524ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = null;
525ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
526ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
530ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the elevation for this popup window in pixels
531ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setElevation(float)
532ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
533ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
534ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public float getElevation() {
535ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        return mElevation;
536ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
537ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
538ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
539ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the elevation for this popup window.
540ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     *
541ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @param elevation the popup's elevation in pixels
542ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getElevation()
543ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
544ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
545ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public void setElevation(float elevation) {
546ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = elevation;
547ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
548ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
549ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the animation style to use the popup appears and disappears</p>
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the animation style to use the popup appears and disappears
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAnimationStyle() {
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
557393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
55954ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * Set the flag on popup to ignore cheek press events; by default this flag
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is set to false
56154ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * which means the popup will not ignore cheek press dispatch events.
5625435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
566393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setIgnoreCheekPress() {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIgnoreCheekPress = true;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5725435a30ae552391f14009c4459731ae149675b18Alan Viverette
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the animation style resource for this popup.</p>
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param animationStyle animation style to use when the popup appears
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      and disappears.  Set to -1 for the default animation, 0 for no
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      animation, or a resource identifier for an explicit animation.
5845435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAnimationStyle(int animationStyle) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationStyle = animationStyle;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5905435a30ae552391f14009c4459731ae149675b18Alan Viverette
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the view used as the content of the popup window.</p>
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a {@link android.view.View} representing the popup's content
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setContentView(android.view.View)
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getContentView() {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContentView;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the popup's content. The content is represented by an instance
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of {@link android.view.View}.</p>
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
60681f08086b44a117097960195d2c9072e29644962Gilles Debunne     * <p>This method has no effect if called when the popup is showing.</p>
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the new content for the popup
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getContentView()
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setContentView(View contentView) {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing()) {
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContentView = contentView;
619448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
6200c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext == null && mContentView != null) {
621448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = mContentView.getContext();
622448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
623448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
6240c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mWindowManager == null && mContentView != null) {
625448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
626448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
627393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
628393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // Setting the default for attachedInDecor based on SDK version here
629393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // instead of in the constructor since we might not have the context
630393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // object in the constructor. We only want to set default here if the
631393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // app hasn't already set the attachedInDecor.
632393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mContext != null && !mAttachedInDecorSet) {
633393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // Attach popup window in decor frame of parent window by default for
634393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current
635393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // behavior of not attaching to decor frame for older SDKs.
636393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion
637393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale                    >= Build.VERSION_CODES.LOLLIPOP_MR1);
638393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
639393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set a callback for all touch events being dispatched to the popup
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window.
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchInterceptor(OnTouchListener l) {
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchInterceptor = l;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether the popup window can grab the focus.</p>
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is focusable, false otherwise
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setFocusable(boolean)
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isFocusable() {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFocusable;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the focusability of the popup window. When focusable, the
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will grab the focus from the current focused widget if the popup
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * contains a focusable {@link android.view.View}.  By default a popup
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is not focusable.</p>
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup should grab focus, false otherwise.
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isFocusable()
6745435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFocusable(boolean focusable) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFocusable = focusable;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the current value in {@link #setInputMethodMode(int)}.
6835435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setInputMethodMode(int)
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getInputMethodMode() {
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputMethodMode;
6885435a30ae552391f14009c4459731ae149675b18Alan Viverette
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6905435a30ae552391f14009c4459731ae149675b18Alan Viverette
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control how the popup operates with an input method: one of
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #INPUT_METHOD_NOT_NEEDED}.
6955435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6995435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getInputMethodMode()
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethodMode(int mode) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputMethodMode = mode;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
706374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
707374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
708374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Sets the operating mode for the soft input area.
709374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
710374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @param mode The desired mode, see
711374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
712374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        for the full list
713374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
714374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
715374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #getSoftInputMode()
716374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
717374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public void setSoftInputMode(int mode) {
718374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        mSoftInputMode = mode;
719374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
720374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
721374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
722374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Returns the current value in {@link #setSoftInputMode(int)}.
723374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
724374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #setSoftInputMode(int)
725374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
726374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
727374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public int getSoftInputMode() {
728374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        return mSoftInputMode;
729374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
7305435a30ae552391f14009c4459731ae149675b18Alan Viverette
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window receives touch events.</p>
7335435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is touchable, false otherwise
7355435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setTouchable(boolean)
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isTouchable() {
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTouchable;
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the touchability of the popup window. When touchable, the
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will receive touch events, otherwise touch events will go to the
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window below it. By default the window is touchable.</p>
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive touch events, false otherwise
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isTouchable()
7545435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchable(boolean touchable) {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchable = touchable;
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window will be informed of touch events
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * outside of its window.</p>
7645435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is outside touchable, false otherwise
7665435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setOutsideTouchable(boolean)
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isOutsideTouchable() {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOutsideTouchable;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Controls whether the pop-up will be informed of touch events outside
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of its window.  This only makes sense for pop-ups that are touchable
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but not focusable, which means touches outside of the window will
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be delivered to the window behind.  The default is false.</p>
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive outside
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * touch events, false otherwise
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isOutsideTouchable()
7875435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOutsideTouchable(boolean touchable) {
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOutsideTouchable = touchable;
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether clipping of the popup window is enabled.</p>
7965435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the clipping is enabled, false otherwise
7985435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setClippingEnabled(boolean)
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isClippingEnabled() {
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mClippingEnabled;
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Allows the popup window to extend beyond the bounds of the screen. By default the
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is clipped to the screen boundaries. Setting this to false will allow windows to be
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accurately positioned.</p>
8095435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param enabled false if the window should be allowed to extend outside of the screen
8155435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isClippingEnabled()
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setClippingEnabled(boolean enabled) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mClippingEnabled = enabled;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
82456c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * Clip this popup window to the screen, but not to the containing window.
82556c2d337e02a275397fc9d0460dca90977f199acAdam Powell     *
82656c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @param enabled True to clip to the screen.
82756c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @hide
82856c2d337e02a275397fc9d0460dca90977f199acAdam Powell     */
82956c2d337e02a275397fc9d0460dca90977f199acAdam Powell    public void setClipToScreenEnabled(boolean enabled) {
83056c2d337e02a275397fc9d0460dca90977f199acAdam Powell        mClipToScreen = enabled;
83156c2d337e02a275397fc9d0460dca90977f199acAdam Powell        setClippingEnabled(!enabled);
83256c2d337e02a275397fc9d0460dca90977f199acAdam Powell    }
833348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell
834348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    /**
835348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * Allow PopupWindow to scroll the anchor's parent to provide more room
836348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * for the popup. Enabled by default.
837348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     *
838348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * @param enabled True to scroll the anchor's parent when more room is desired by the popup.
839348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     */
840348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    void setAllowScrollingAnchorParent(boolean enabled) {
841348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mAllowScrollingAnchorParent = enabled;
842348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    }
8435435a30ae552391f14009c4459731ae149675b18Alan Viverette
84456c2d337e02a275397fc9d0460dca90977f199acAdam Powell    /**
84501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Indicates whether the popup window supports splitting touches.</p>
8465435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
84701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @return true if the touch splitting is enabled, false otherwise
8485435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
84901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #setSplitTouchEnabled(boolean)
85001ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
85101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public boolean isSplitTouchEnabled() {
85246e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (mSplitTouchEnabled < 0 && mContext != null) {
85346e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown            return mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
85446e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        }
85546e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        return mSplitTouchEnabled == 1;
85601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
85701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
85801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
85901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Allows the popup window to split touches across other windows that also
86046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * support split touch.  When this flag is false, the first pointer
86101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * that goes down determines the window to which all subsequent touches
86246e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * go until all pointers go up.  When this flag is true, each pointer
86301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * (not necessarily the first) that goes down determines the window
86401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to which all subsequent touches of that pointer will go until that
86501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * pointer goes up thereby enabling touches with multiple pointers
86601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to be split across multiple windows.</p>
86701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     *
86801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @param enabled true if the split touches should be enabled, false otherwise
86901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #isSplitTouchEnabled()
87001ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
87101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public void setSplitTouchEnabled(boolean enabled) {
87246e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        mSplitTouchEnabled = enabled ? 1 : 0;
87301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
87401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
87501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
876ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Indicates whether the popup window will be forced into using absolute screen coordinates
877ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * for positioning.</p>
878ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
879ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @return true if the window will always be positioned in screen coordinates.
880ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
881ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
882ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public boolean isLayoutInScreenEnabled() {
883ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        return mLayoutInScreen;
884ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
885ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
886ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
887ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Allows the popup window to force the flag
888ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior.
889ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * This will cause the popup to be positioned in absolute screen coordinates.</p>
890ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
891ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @param enabled true if the popup should always be positioned in screen coordinates
892ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
893ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
894ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public void setLayoutInScreenEnabled(boolean enabled) {
895ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        mLayoutInScreen = enabled;
896ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
897ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
898ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
899393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>Indicates whether the popup window will be attached in the decor frame of its parent
900393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * window.
901393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
902393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @return true if the window will be attached to the decor frame of its parent window.
903393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
904393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see #setAttachedInDecor(boolean)
905393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
906393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
907393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public boolean isAttachedInDecor() {
908393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        return mAttachedInDecor;
909393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
910393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
911393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
912393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>This will attach the popup window to the decor frame of the parent window to avoid
913393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * overlaping with screen decorations like the navigation bar. Overrides the default behavior of
914393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}.
915393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
916393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or
917393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * greater and cleared on lesser SDK versions.
918393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
919393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @param enabled true if the popup should be attached to the decor frame of its parent window.
920393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
921393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
922393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
923393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public void setAttachedInDecor(boolean enabled) {
924393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecor = enabled;
925393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecorSet = true;
926393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
927393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
928393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
9290bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * Allows the popup window to force the flag
9300bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
9310bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * This will cause the popup to inset its content to account for system windows overlaying
9320bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * the screen, such as the status bar.
9330bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
9340bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
9350bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
9360bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @param enabled true if the popup's views should inset content to account for system windows,
9370bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *                the way that decor views behave for full-screen windows.
9380bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @hide
9390bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     */
9400bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    public void setLayoutInsetDecor(boolean enabled) {
9410bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        mLayoutInsetDecor = enabled;
9420bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    }
9430bd1d0a15294345bf88b20df28466907f982cec7Adam Powell
9440bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    /**
94580ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * Set the layout type for this window.
94680ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * <p>
94780ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * See {@link WindowManager.LayoutParams#type} for possible values.
948574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     *
949574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @param layoutType Layout type for this window.
95036344a90c226c90243e4e02bfb13589e120431ddChris Banes     *
95136344a90c226c90243e4e02bfb13589e120431ddChris Banes     * @see WindowManager.LayoutParams#type
952574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
953574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public void setWindowLayoutType(int layoutType) {
954574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        mWindowLayoutType = layoutType;
955574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
956574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
957574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
95836344a90c226c90243e4e02bfb13589e120431ddChris Banes     * Returns the layout type for this window.
95936344a90c226c90243e4e02bfb13589e120431ddChris Banes     *
96036344a90c226c90243e4e02bfb13589e120431ddChris Banes     * @see #setWindowLayoutType(int)
961574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
962574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public int getWindowLayoutType() {
963574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        return mWindowLayoutType;
964574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
965574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
966574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
967e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * Set whether this window is touch modal or if outside touches will be sent to
968e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * other windows behind it.
969e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * @hide
970e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     */
971e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    public void setTouchModal(boolean touchModal) {
972e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        mNotTouchModal = !touchModal;
973e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    }
974e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell
975e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    /**
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the width and height measure specs that are given to the
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window manager by the popup.  By default these are 0, meaning that
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the current width or height is requested as an explicit size from
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the window manager.  You can supply
9805435a30ae552391f14009c4459731ae149675b18Alan Viverette     * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or
981980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * spec supplied instead, replacing the absolute width and height that
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * has been set in the popup.</p>
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown.</p>
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param widthSpec an explicit width measure spec mode, either
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
990980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * width.
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param heightSpec an explicit height measure spec mode, either
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
994980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * height.
996259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *
997259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @deprecated Use {@link #setWidth(int)} and {@link #setHeight(int)}.
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
999259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    @Deprecated
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWindowLayoutMode(int widthSpec, int heightSpec) {
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidthMode = widthSpec;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeightMode = heightSpec;
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10045435a30ae552391f14009c4459731ae149675b18Alan Viverette
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1006259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Returns the popup's height MeasureSpec.
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the height MeasureSpec of the popup
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHeight(int)
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getHeight() {
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeight;
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1016259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Sets the popup's height MeasureSpec.
1017259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1018259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
1019259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the height MeasureSpec of the popup
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getHeight()
10235435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHeight(int height) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeight = height;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1030259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Returns the popup's width MeasureSpec.
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the width MeasureSpec of the popup
10335435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #setWidth(int)
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWidth() {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWidth;
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1040259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Sets the popup's width MeasureSpec.
1041259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1042259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
1043259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the width MeasureSpec of the popup
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getWidth()
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWidth(int width) {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidth = width;
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
105475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Sets whether the popup window should overlap its anchor view when
105575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
105675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
105775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the popup is showing, calling this method will take effect only
105875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the next time the popup is shown.
105975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
106075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @param overlapAnchor Whether the popup should overlap its anchor.
106175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
106275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #getOverlapAnchor()
106375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #isShowing()
106475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
106575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public void setOverlapAnchor(boolean overlapAnchor) {
106675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mOverlapAnchor = overlapAnchor;
106775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
106875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
106975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
107075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Returns whether the popup window should overlap its anchor view when
107175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
107275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
107375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @return Whether the popup should overlap its anchor.
107475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
107575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #setOverlapAnchor(boolean)
107675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
107775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public boolean getOverlapAnchor() {
107875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        return mOverlapAnchor;
107975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
108075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
108175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether this popup window is showing on screen.</p>
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is showing, false otherwise
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowing() {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsShowing;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Display the content view in a popup window at the specified location. If the popup window
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams}
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for more information on how gravity and the x and y parameters are related. Specifying
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>Gravity.LEFT | Gravity.TOP</code>.
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </p>
10985435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity the gravity which controls the placement of the popup window
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the popup's x location offset
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the popup's y location offset
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAtLocation(View parent, int gravity, int x, int y) {
11058ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell        showAtLocation(parent.getWindowToken(), gravity, x, y);
11068ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    }
11078ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell
11088ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    /**
11098ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * Display the content view in a popup window at the specified location.
11108ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
11118ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param token Window token to use for creating the new window
11128ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param gravity the gravity which controls the placement of the popup window
11138ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param x the popup's x location offset
11148ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param y the popup's y location offset
11158ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
11168ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @hide Internal use only. Applications should use
11178ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *       {@link #showAtLocation(View, int, int, int)} instead.
11188ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     */
11198ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    public void showAtLocation(IBinder token, int gravity, int x, int y) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1124e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1125e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1126634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        unregisterForViewTreeChanges();
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = false;
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1131e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(token);
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
1133e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1134e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Only override the default if some gravity was specified.
1135e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (gravity != Gravity.NO_GRAVITY) {
1136e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.gravity = gravity;
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1138e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.x = x;
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.y = y;
1141e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
114675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view. If there is not enough room on screen to show
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup in its entirety, this method tries to find a parent scroll
114975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view to scroll. If no parent scroll view can be scrolled, the
115075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * bottom-left corner of the popup is pinned at the top left corner of the
115175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * anchor view.
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor) {
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        showAsDropDown(anchor, 0, 0);
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
116275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view offset by the specified x and y coordinates.
116475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
116575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
116675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * scroll view can be scrolled, the bottom-left corner of the popup is
116775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * pinned at the top left corner of the anchor view.
116875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
116975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
117075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
117354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
117454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor, int xoff, int yoff) {
117954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        showAsDropDown(anchor, xoff, yoff, DEFAULT_ANCHORED_GRAVITY);
118054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
118154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
118254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    /**
118375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Displays the content view in a popup window anchored to the corner of
118475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * another view. The window is positioned according to the specified
118575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * gravity and offset by the specified x and y coordinates.
118675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
118775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
118875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
118975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view can be scrolled, the specified vertical gravity will be ignored and
119075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the popup will anchor itself such that it is visible.
119175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
119275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
119375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
119454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
119554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param anchor the view on which to pin the popup window
119654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
119754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
119854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param gravity Alignment of the popup relative to the anchor
119954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
120054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @see #dismiss()
120154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     */
120254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1207e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1208e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1209634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        registerForViewTreeChanges(anchor, xoff, yoff, gravity);
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = true;
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1214e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1217e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff, gravity);
1218e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        updateAboveAnchor(aboveAnchor);
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12233e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    private void updateAboveAnchor(boolean aboveAnchor) {
12243e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        if (aboveAnchor != mAboveAnchor) {
12253e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            mAboveAnchor = aboveAnchor;
12263e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
1227697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            if (mBackground != null && mBackgroundView != null) {
1228697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // If the background drawable provided was a StateListDrawable
1229697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // with above-anchor and below-anchor states, use those.
1230697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // Otherwise, rely on refreshDrawableState to do the job.
12313e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                if (mAboveAnchorBackgroundDrawable != null) {
12323e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    if (mAboveAnchor) {
1233697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                        mBackgroundView.setBackground(mAboveAnchorBackgroundDrawable);
12343e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    } else {
1235697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                        mBackgroundView.setBackground(mBelowAnchorBackgroundDrawable);
12363e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    }
12373e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                } else {
1238697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                    mBackgroundView.refreshDrawableState();
12393e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                }
12403e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            }
12413e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        }
12423e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    }
12433e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicates whether the popup is showing above (the y coordinate of the popup's bottom
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is less than the y coordinate of the anchor) or below the anchor view (the y coordinate
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the popup is greater than y coordinate of the anchor's bottom).
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The value returned
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by this method is meaningful only after {@link #showAsDropDown(android.view.View)}
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #showAsDropDown(android.view.View, int, int)} was invoked.
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if this popup is showing above the anchor view, false otherwise.
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAboveAnchor() {
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAboveAnchor;
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1260e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * Prepare the popup by embedding it into a new ViewGroup if the background
1261e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * drawable is not null. If embedding is required, the layout parameters'
1262e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * height is modified to take into account the background's padding.
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void preparePopup(WindowManager.LayoutParams p) {
1267448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (mContentView == null || mContext == null || mWindowManager == null) {
1268448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            throw new IllegalStateException("You must specify a valid content view by "
1269448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy                    + "calling setContentView() before attempting to show the popup.");
1270448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
1271448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
12728fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // The old decor view may be transitioning out. Make sure it finishes
12738fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // and cleans up before we try to create another one.
12748fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (mDecorView != null) {
12758fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mDecorView.cancelTransitions();
12768fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
12778fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
12785435a30ae552391f14009c4459731ae149675b18Alan Viverette        // When a background is available, we embed the content view within
12795435a30ae552391f14009c4459731ae149675b18Alan Viverette        // another view that owns the background drawable.
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
1281697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView = createBackgroundView(mContentView);
1282697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView.setBackground(mBackground);
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1284697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView = mContentView;
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1286ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
1287697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mDecorView = createDecorView(mBackgroundView);
12885435a30ae552391f14009c4459731ae149675b18Alan Viverette
12895435a30ae552391f14009c4459731ae149675b18Alan Viverette        // The background owner should be elevated so that it casts a shadow.
1290697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mBackgroundView.setElevation(mElevation);
12915435a30ae552391f14009c4459731ae149675b18Alan Viverette
12925435a30ae552391f14009c4459731ae149675b18Alan Viverette        // We may wrap that in another view, so we'll need to manually specify
12935435a30ae552391f14009c4459731ae149675b18Alan Viverette        // the surface insets.
1294697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        final int surfaceInset = (int) Math.ceil(mBackgroundView.getZ() * 2);
12955435a30ae552391f14009c4459731ae149675b18Alan Viverette        p.surfaceInsets.set(surfaceInset, surfaceInset, surfaceInset, surfaceInset);
12965435a30ae552391f14009c4459731ae149675b18Alan Viverette        p.hasManualSurfaceInsets = true;
12975435a30ae552391f14009c4459731ae149675b18Alan Viverette
1298b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        mPopupViewInitialLayoutDirectionInherited =
12995435a30ae552391f14009c4459731ae149675b18Alan Viverette                (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPopupWidth = p.width;
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPopupHeight = p.height;
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13055435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a PopupViewContainer.
13065435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
13075435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
13085435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a PopupViewContainer that wraps the content view
13095435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
13105435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupBackgroundView createBackgroundView(View contentView) {
13115435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
13125435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
13135435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
13145435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.WRAP_CONTENT;
13155435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
13165435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.MATCH_PARENT;
13175435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
13185435a30ae552391f14009c4459731ae149675b18Alan Viverette
13195435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView backgroundView = new PopupBackgroundView(mContext);
13205435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView.LayoutParams listParams = new PopupBackgroundView.LayoutParams(
13215435a30ae552391f14009c4459731ae149675b18Alan Viverette                ViewGroup.LayoutParams.MATCH_PARENT, height);
13225435a30ae552391f14009c4459731ae149675b18Alan Viverette        backgroundView.addView(contentView, listParams);
13235435a30ae552391f14009c4459731ae149675b18Alan Viverette
13245435a30ae552391f14009c4459731ae149675b18Alan Viverette        return backgroundView;
13255435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
13265435a30ae552391f14009c4459731ae149675b18Alan Viverette
13275435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
13285435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a FrameLayout.
13295435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
13305435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
13315435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a FrameLayout that wraps the content view
13325435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
13335435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView createDecorView(View contentView) {
13345435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
13355435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
13365435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (layoutParams != null && layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) {
13375435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.WRAP_CONTENT;
13385435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
13395435a30ae552391f14009c4459731ae149675b18Alan Viverette            height = ViewGroup.LayoutParams.MATCH_PARENT;
13405435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
13415435a30ae552391f14009c4459731ae149675b18Alan Viverette
13425435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupDecorView decorView = new PopupDecorView(mContext);
13435435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.addView(contentView, ViewGroup.LayoutParams.MATCH_PARENT, height);
13445435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipChildren(false);
13455435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipToPadding(false);
13465435a30ae552391f14009c4459731ae149675b18Alan Viverette
13475435a30ae552391f14009c4459731ae149675b18Alan Viverette        return decorView;
13485435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
13495435a30ae552391f14009c4459731ae149675b18Alan Viverette
13505435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Invoke the popup window by adding the content view to the window
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * manager.</p>
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The content view must be non-null when this method is invoked.</p>
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void invokePopup(WindowManager.LayoutParams p) {
13590c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext != null) {
13600c0b768e1514280812321854db6dfba723c3d169Romain Guy            p.packageName = mContext.getPackageName();
13610c0b768e1514280812321854db6dfba723c3d169Romain Guy        }
13625435a30ae552391f14009c4459731ae149675b18Alan Viverette
13638fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
13648fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.setFitsSystemWindows(mLayoutInsetDecor);
13655435a30ae552391f14009c4459731ae149675b18Alan Viverette
13668fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        setLayoutDirectionFromAnchor();
13675435a30ae552391f14009c4459731ae149675b18Alan Viverette
13688fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mWindowManager.addView(decorView, p);
136995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
137095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        if (mEnterTransition != null) {
137195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            decorView.requestEnterTransition(mEnterTransition);
137295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        }
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1375b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private void setLayoutDirectionFromAnchor() {
1376b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        if (mAnchor != null) {
1377b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            View anchor = mAnchor.get();
1378b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
13795435a30ae552391f14009c4459731ae149675b18Alan Viverette                mDecorView.setLayoutDirection(anchor.getLayoutDirection());
1380b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            }
1381b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        }
1382b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    }
1383b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Generate the layout parameters for the popup window.</p>
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param token the window token used to bind the popup's window
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the layout parameters to pass to the window manager
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1391e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette    private WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
1392e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
1393e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1394e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // These gravity settings put the view at the top left corner of the
1395e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // screen. The view is then positioned to the appropriate location by
1396e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // setting the x and y offsets to match the anchor's bottom-left
1397e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // corner.
1398aac0d4ed026d1cfbcf3fa81c6e4eb96f4347ca17Fabrice Di Meglio        p.gravity = Gravity.START | Gravity.TOP;
1399e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.flags = computeFlags(p.flags);
1400e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.type = mWindowLayoutType;
1401e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.token = token;
1402e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.softInputMode = mSoftInputMode;
1403e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.windowAnimations = computeAnimationResource();
1404e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = mBackground.getOpacity();
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = PixelFormat.TRANSLUCENT;
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1410e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1411e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mHeightMode < 0) {
1412e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeightMode;
1413e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1414e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeight;
1415e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1416e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1417e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mWidthMode < 0) {
1418e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidthMode;
1419e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1420e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidth;
1421e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1422e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
14238216eb2221ad5ad6615d3966f43844268756f3c8Wale Ogunwale        p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH
14248216eb2221ad5ad6615d3966f43844268756f3c8Wale Ogunwale                | PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
1425a1eb439eee65138280c560f96e2a6896f9c9112cRobert Carr
1426e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Used for debugging.
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return p;
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeFlags(int curFlags) {
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        curFlags &= ~(
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
1439ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
1440ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if(mIgnoreCheekPress) {
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mFocusable) {
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputMethodMode == INPUT_METHOD_NEEDED) {
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mInputMethodMode == INPUT_METHOD_NOT_NEEDED) {
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mTouchable) {
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1455c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (mOutsideTouchable) {
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mClippingEnabled) {
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
146146e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (isSplitTouchEnabled()) {
146201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown            curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
146301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown        }
1464ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        if (mLayoutInScreen) {
1465ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
1466ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        }
14670bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        if (mLayoutInsetDecor) {
14680bd1d0a15294345bf88b20df28466907f982cec7Adam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
14690bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        }
1470e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        if (mNotTouchModal) {
1471e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
1472e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        }
1473393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mAttachedInDecor) {
1474393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale          curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
1475393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return curFlags;
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1478393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeAnimationResource() {
14805435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (mAnimationStyle == ANIMATION_STYLE_DEFAULT) {
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsDropdown) {
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mAboveAnchor
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ? com.android.internal.R.style.Animation_DropDownUp
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : com.android.internal.R.style.Animation_DropDownDown;
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1490560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1492560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * Positions the popup window on screen. When the popup window is too tall
1493560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to fit under the anchor, a parent scroll view is seeked and scrolled up
1494560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to reclaim space. If scrolling is not possible or not enough, the popup
1495560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * window gets moved on top of the anchor.
1496560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * <p>
1497560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * The height must have been set on the layout parameters prior to calling
1498560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * this method.
14995435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which the popup window must be anchored
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters used to display the drop down
1502560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param xoff horizontal offset used to adjust for background padding
1503560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param yoff vertical offset used to adjust for background padding
1504560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param gravity horizontal gravity specifying popup alignment
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is translated upwards to fit on screen
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1507560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff,
1508560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            int yoff, int gravity) {
150962e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        final int anchorHeight = anchor.getHeight();
1510560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int anchorWidth = anchor.getWidth();
1511560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        if (mOverlapAnchor) {
1512560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            yoff -= anchorHeight;
1513560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        }
1514560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationInWindow(mDrawingLocation);
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.x = mDrawingLocation[0] + xoff;
151762e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        p.y = mDrawingLocation[1] + anchorHeight + yoff;
151854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1519560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
1520560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                & Gravity.HORIZONTAL_GRAVITY_MASK;
152154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        if (hgrav == Gravity.RIGHT) {
1522560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Flip the location to align the right sides of the popup and
1523560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // anchor instead of left.
1524560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            p.x -= mPopupWidth - anchorWidth;
152554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        }
1526560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean onTop = false;
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
152954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        p.gravity = Gravity.LEFT | Gravity.TOP;
153054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationOnScreen(mScreenLocation);
15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect displayFrame = new Rect();
15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getWindowVisibleDisplayFrame(displayFrame);
153462e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell
1535560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int screenY = mScreenLocation[1] + anchorHeight + yoff;
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View root = anchor.getRootView();
1537560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        if (screenY + mPopupHeight > displayFrame.bottom
1538560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                || p.x + mPopupWidth - root.getWidth() > 0) {
1539560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // If the drop down disappears at the bottom of the screen, we try
1540560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // to scroll a parent scrollview or move the drop down back up on
1541560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // top of the edit box.
1542b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell            if (mAllowScrollingAnchorParent) {
1543560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final int scrollX = anchor.getScrollX();
1544560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final int scrollY = anchor.getScrollY();
1545560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                final Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
1546560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                        scrollY + mPopupHeight + anchorHeight + yoff);
1547b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell                anchor.requestRectangleOnScreen(r, true);
1548b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell            }
15493e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
1550560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Now we re-evaluate the space available, and decide from that
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // whether the pop-up will go above or below the anchor.
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            anchor.getLocationInWindow(mDrawingLocation);
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.x = mDrawingLocation[0] + xoff;
1554560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            p.y = mDrawingLocation[1] + anchorHeight + yoff;
155554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1556560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Preserve the gravity adjustment.
155754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            if (hgrav == Gravity.RIGHT) {
1558560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                p.x -= mPopupWidth - anchorWidth;
155954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            }
1560560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1561560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            // Determine whether there is more space above or below the anchor.
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            anchor.getLocationOnScreen(mScreenLocation);
1563560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            onTop = (displayFrame.bottom - mScreenLocation[1] - anchorHeight - yoff) <
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    (mScreenLocation[1] - yoff - displayFrame.top);
1565ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            if (!mOverlapAnchor) {
1566ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                if (onTop) {
1567ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    p.gravity = Gravity.LEFT | Gravity.BOTTOM;
1568ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    p.y = root.getHeight() - mDrawingLocation[1] + yoff;
1569ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                } else {
1570ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    p.y = mDrawingLocation[1] + anchorHeight + yoff;
1571ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                }
15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
157556c2d337e02a275397fc9d0460dca90977f199acAdam Powell        if (mClipToScreen) {
15767c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            final int winOffsetX = mScreenLocation[0] - mDrawingLocation[0];
15777c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            final int winOffsetY = mScreenLocation[1] - mDrawingLocation[1];
15787c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            p.x += winOffsetX;
15797c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            p.y += winOffsetY;
158056c2d337e02a275397fc9d0460dca90977f199acAdam Powell            final int displayFrameWidth = displayFrame.right - displayFrame.left;
1581560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            final int right = p.x + p.width;
15827c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            if (right > displayFrame.right) {
15837c9732db0e450785f70d634fee4037b5e887d911Chong Zhang                p.x -= right - displayFrame.right;
158456c2d337e02a275397fc9d0460dca90977f199acAdam Powell            }
1585560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
158656c2d337e02a275397fc9d0460dca90977f199acAdam Powell            if (p.x < displayFrame.left) {
158756c2d337e02a275397fc9d0460dca90977f199acAdam Powell                p.x = displayFrame.left;
158856c2d337e02a275397fc9d0460dca90977f199acAdam Powell                p.width = Math.min(p.width, displayFrameWidth);
158956c2d337e02a275397fc9d0460dca90977f199acAdam Powell            }
159056c2d337e02a275397fc9d0460dca90977f199acAdam Powell
1591ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            if (mOverlapAnchor) {
1592ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                final int bottom = p.y + p.height;
1593ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                if (bottom > displayFrame.bottom) {
15947c9732db0e450785f70d634fee4037b5e887d911Chong Zhang                    p.y -= bottom - displayFrame.bottom;
15955f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell                }
15965f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            } else {
1597ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                if (onTop) {
1598ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    final int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
1599ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    if (popupTop < 0) {
1600ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                        p.y += popupTop;
1601ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    }
1602ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                } else {
1603ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                    p.y = Math.max(p.y, displayFrame.top);
1604ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg                }
16055f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            }
16067c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            p.x -= winOffsetX;
16077c9732db0e450785f70d634fee4037b5e887d911Chong Zhang            p.y -= winOffsetY;
160856c2d337e02a275397fc9d0460dca90977f199acAdam Powell        }
160956c2d337e02a275397fc9d0460dca90977f199acAdam Powell
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
1611560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return onTop;
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16145435a30ae552391f14009c4459731ae149675b18Alan Viverette
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
16205435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1625b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(@NonNull View anchor) {
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getMaxAvailableHeight(anchor, 0);
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yOffset y offset from the view's bottom edge
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1640b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(@NonNull View anchor, int yOffset) {
164198acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        return getMaxAvailableHeight(anchor, yOffset, false);
164298acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    }
16435435a30ae552391f14009c4459731ae149675b18Alan Viverette
164498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    /**
164598acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * Returns the maximum height that is available for the popup to be
164698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * completely shown, optionally ignoring any bottom decorations such as
164798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the input method. It is recommended that this height be the maximum for
164898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the popup's height, otherwise it is possible that the popup will be
164998acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * clipped.
16505435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
165198acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param anchor The view on which the popup window must be anchored.
165298acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param yOffset y offset from the view's bottom edge
165398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param ignoreBottomDecorations if true, the height returned will be
165498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        all the way to the bottom of the display, ignoring any
165598acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        bottom decorations
165698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @return The maximum available height for the popup to be completely
165798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *         shown.
165898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     */
1659b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(
1660b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette            @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect displayFrame = new Rect();
16628175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        if (ignoreBottomDecorations) {
16638175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi            anchor.getWindowDisplayFrame(displayFrame);
16648175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        } else {
16658175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi            anchor.getWindowVisibleDisplayFrame(displayFrame);
16668175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        }
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int[] anchorPos = mDrawingLocation;
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationOnScreen(anchorPos);
16705435a30ae552391f14009c4459731ae149675b18Alan Viverette
16718175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        final int bottomEdge = displayFrame.bottom;
1672ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg
1673ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        final int distanceToBottom;
1674ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        if (mOverlapAnchor) {
1675ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            distanceToBottom = bottomEdge - anchorPos[1] - yOffset;
1676ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        } else {
1677ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
1678ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        }
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // anchorPos[1] is distance from anchor to top of screen
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int returnedHeight = Math.max(distanceToBottom, distanceToTop);
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBackground.getPadding(mTempRect);
16855435a30ae552391f14009c4459731ae149675b18Alan Viverette            returnedHeight -= mTempRect.top + mTempRect.bottom;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16875435a30ae552391f14009c4459731ae149675b18Alan Viverette
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return returnedHeight;
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16905435a30ae552391f14009c4459731ae149675b18Alan Viverette
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16927878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * Disposes of the popup window. This method can be invoked only after
16937878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * {@link #showAsDropDown(android.view.View)} has been executed. Failing
16947878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * that, calling this method will have no effect.
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16965435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #showAsDropDown(android.view.View)
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dismiss() {
16998fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (!isShowing() || mIsTransitioningToDismiss) {
1700e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            return;
1701e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
170206f938e8aa56cd89ab0bdb04c8b946392c428dd1Svetoslav Ganov
17038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
17048fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final View contentView = mContentView;
17058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
17068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewGroup contentHolder;
17078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewParent contentParent = contentView.getParent();
17088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentParent instanceof ViewGroup) {
17098fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = ((ViewGroup) contentParent);
17108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        } else {
17118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = null;
17128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
17138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
17148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // Ensure any ongoing or pending transitions are canceled.
17158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.cancelTransitions();
17168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
1717e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        mIsShowing = false;
17188fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = true;
1719b82d074038f4c8d86e1bd4f3fa4d3780bd4bcba5Craig Mautner
1720634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // This method may be called as part of window detachment, in which
1721634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // case the anchor view (and its root) will still return true from
1722634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // isAttachedToWindow() during execution of this method; however, we
1723634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // can expect the OnAttachStateChangeListener to have been called prior
1724634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // to executing this method, so we can rely on that instead.
172595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final Transition exitTransition = mExitTransition;
172621d361806c9e2dce5bae5b30f44be5ad87f32c22Alan Viverette        if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
1727dbd299de2a07a2a0a490d4f37cf92870bf87d6c1Yohei Yukawa            // The decor view is non-interactive and non-IME-focusable during exit transitions.
172895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
172995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
173095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
1731dbd299de2a07a2a0a490d4f37cf92870bf87d6c1Yohei Yukawa            p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
173295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            mWindowManager.updateViewLayout(decorView, p);
173395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
1734634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // Once we start dismissing the decor view, all state (including
1735634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // the anchor root) needs to be moved to the decor view since we
1736634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // may open another popup while it's busy exiting.
1737634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
173891098574f90277128415e9593cce1e495cc51465Alan Viverette            final Rect epicenter = getTransitionEpicenter();
173995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            exitTransition.setEpicenterCallback(new EpicenterCallback() {
174095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                @Override
174195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                public Rect onGetEpicenter(Transition transition) {
174295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                    return epicenter;
174395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                }
174495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            });
1745634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            decorView.startExitTransition(exitTransition, anchorRoot,
1746634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    new TransitionListenerAdapter() {
1747634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        @Override
1748634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        public void onTransitionEnd(Transition transition) {
17497970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette                            dismissImmediate(decorView, contentHolder, contentView);
1750634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        }
1751634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    });
1752e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
17537970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette            dismissImmediate(decorView, contentHolder, contentView);
17547878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette        }
17557878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
175695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        // Clears the anchor view.
1757634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        unregisterForViewTreeChanges();
17587970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette
17597970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette        if (mOnDismissListener != null) {
17607970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette            mOnDismissListener.onDismiss();
17617970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette        }
17625435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
17635435a30ae552391f14009c4459731ae149675b18Alan Viverette
176491098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
176591098574f90277128415e9593cce1e495cc51465Alan Viverette     * Returns the window-relative epicenter bounds to be used by enter and
176691098574f90277128415e9593cce1e495cc51465Alan Viverette     * exit transitions.
176791098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
176891098574f90277128415e9593cce1e495cc51465Alan Viverette     * <strong>Note:</strong> This is distinct from the rect passed to
176991098574f90277128415e9593cce1e495cc51465Alan Viverette     * {@link #setEpicenterBounds(Rect)}, which is anchor-relative.
177091098574f90277128415e9593cce1e495cc51465Alan Viverette     *
177191098574f90277128415e9593cce1e495cc51465Alan Viverette     * @return the window-relative epicenter bounds to be used by enter and
177291098574f90277128415e9593cce1e495cc51465Alan Viverette     *         exit transitions
177391098574f90277128415e9593cce1e495cc51465Alan Viverette     */
177491098574f90277128415e9593cce1e495cc51465Alan Viverette    private Rect getTransitionEpicenter() {
177595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final View anchor = mAnchor != null ? mAnchor.get() : null;
177695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final View decor = mDecorView;
177795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        if (anchor == null || decor == null) {
177895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            return null;
177995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        }
178095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
178195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final int[] anchorLocation = anchor.getLocationOnScreen();
178295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final int[] popupLocation = mDecorView.getLocationOnScreen();
178395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
178495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        // Compute the position of the anchor relative to the popup.
178595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final Rect bounds = new Rect(0, 0, anchor.getWidth(), anchor.getHeight());
178695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        bounds.offset(anchorLocation[0] - popupLocation[0], anchorLocation[1] - popupLocation[1]);
178791098574f90277128415e9593cce1e495cc51465Alan Viverette
178891098574f90277128415e9593cce1e495cc51465Alan Viverette        // Use anchor-relative epicenter, if specified.
178991098574f90277128415e9593cce1e495cc51465Alan Viverette        if (mEpicenterBounds != null) {
179091098574f90277128415e9593cce1e495cc51465Alan Viverette            final int offsetX = bounds.left;
179191098574f90277128415e9593cce1e495cc51465Alan Viverette            final int offsetY = bounds.top;
179291098574f90277128415e9593cce1e495cc51465Alan Viverette            bounds.set(mEpicenterBounds);
179391098574f90277128415e9593cce1e495cc51465Alan Viverette            bounds.offset(offsetX, offsetY);
179491098574f90277128415e9593cce1e495cc51465Alan Viverette        }
179591098574f90277128415e9593cce1e495cc51465Alan Viverette
179695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        return bounds;
179795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette    }
179895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
17995435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
18005435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Removes the popup from the window manager and tears down the supporting
18015435a30ae552391f14009c4459731ae149675b18Alan Viverette     * view hierarchy, if necessary.
18025435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
18037970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette    private void dismissImmediate(View decorView, ViewGroup contentHolder, View contentView) {
18048fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // If this method gets called and the decor view doesn't have a parent,
18058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // then it was either never added or was already removed. That should
18068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // never happen, but it's worth checking to avoid potential crashes.
18078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (decorView.getParent() != null) {
18088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mWindowManager.removeViewImmediate(decorView);
1809df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette        }
1810df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette
18118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentHolder != null) {
18128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder.removeView(contentView);
18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
18158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // This needs to stay until after all transitions have ended since we
18168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // need the reference to cancel transitions in preparePopup().
18178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mDecorView = null;
1818697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mBackgroundView = null;
18198fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = false;
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the listener to be called when the window is dismissed.
18245435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param onDismissListener The listener.
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnDismissListener(OnDismissListener onDismissListener) {
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnDismissListener = onDismissListener;
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18305435a30ae552391f14009c4459731ae149675b18Alan Viverette
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Updates the state of the popup window, if it is currently being displayed,
1833259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * from the currently set state.
1834259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1835259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * This includes:
1836259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <ul>
1837259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setClippingEnabled(boolean)}</li>
1838259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setFocusable(boolean)}</li>
1839259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setIgnoreCheekPress()}</li>
1840259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setInputMethodMode(int)}</li>
1841259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setTouchable(boolean)}</li>
1842259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setAnimationStyle(int)}</li>
1843259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * </ul>
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update() {
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18495435a30ae552391f14009c4459731ae149675b18Alan Viverette
18505435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
18515435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
18525435a30ae552391f14009c4459731ae149675b18Alan Viverette
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = false;
18545435a30ae552391f14009c4459731ae149675b18Alan Viverette
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1866b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
1868b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
18695435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1872d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy
1873d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    /**
1874259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the dimension of the popup window.
1875259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1876259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
1877259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
1878d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     *
1879259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1880259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
1881d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     */
1882d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    public void update(int width, int height) {
18835435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
18845435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
1885d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy        update(p.x, p.y, width, height, false);
1886d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    }
18875435a30ae552391f14009c4459731ae149675b18Alan Viverette
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1889259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1890259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1891259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1892259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1893259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
1897259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1898259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height) {
19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        update(x, y, width, height, false);
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1905259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1906259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1907259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1908259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1909259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
1913259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1914259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
1915259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param force {@code true} to reposition the window even if the specified
1916259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              position already seems to correspond to the LayoutParams,
1917259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              {@code false} to only reposition if needed
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height, boolean force) {
1920259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (width >= 0) {
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastWidth = width;
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setWidth(width);
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1925259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (height >= 0) {
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastHeight = height;
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setHeight(height);
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19345435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
19355435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = force;
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width != -1 && p.width != finalWidth) {
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.width = mLastWidth = finalWidth;
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (height != -1 && p.height != finalHeight) {
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.height = mLastHeight = finalHeight;
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.x != x) {
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.x = x;
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.y != y) {
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.y = y;
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
197298acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
1974b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
19755435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1980259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1981259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1982259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
1983259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
1986259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
1987259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int width, int height) {
199075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        update(anchor, false, 0, 0, true, width, height);
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1994259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1995259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1996259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
1997259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
1998259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
1999259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
2000259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the view later scrolls to move {@code anchor} to a different
2001259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * location, the popup will be moved correspondingly.
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param xoff x offset from the view's left edge
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yoff y offset from the view's bottom edge
2006259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param width the new width, must be >= 0 or -1 to ignore
2007259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param height the new height, must be >= 0 or -1 to ignore
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int xoff, int yoff, int width, int height) {
201075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        update(anchor, true, xoff, yoff, true, width, height);
2011105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2012105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2013105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private void update(View anchor, boolean updateLocation, int xoff, int yoff,
201475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette            boolean updateDimension, int width, int height) {
2015105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
202075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final WeakReference<View> oldAnchor = mAnchor;
202175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
202281f08086b44a117097960195d2c9072e29644962Gilles Debunne        if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
2023634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            registerForViewTreeChanges(anchor, xoff, yoff, mAnchoredGravity);
202481f08086b44a117097960195d2c9072e29644962Gilles Debunne        } else if (needsUpdate) {
202581f08086b44a117097960195d2c9072e29644962Gilles Debunne            // No need to register again if this is a DropDown, showAsDropDown already did.
202681f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorXoff = xoff;
202781f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorYoff = yoff;
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2030105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (updateDimension) {
2031105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (width == -1) {
2032105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                width = mPopupWidth;
2033105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
2034105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mPopupWidth = width;
2035105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
2036105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            if (height == -1) {
2037105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                height = mPopupHeight;
2038105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            } else {
2039105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mPopupHeight = height;
2040105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            }
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2042105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
204375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final WindowManager.LayoutParams p =
20445435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
204575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final int x = p.x;
204675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final int y = p.y;
2047105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (updateLocation) {
204875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette            updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, mAnchoredGravity));
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
205054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell            updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
205154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell                    mAnchoredGravity));
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2053b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
20543e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        update(p.x, p.y, width, height, x != p.x || y != p.y);
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Listener that is called when this popup window is dismissed.
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnDismissListener {
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when this popup window is dismissed.
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onDismiss();
20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2067634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private void unregisterForViewTreeChanges() {
2068634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchor = mAnchor != null ? mAnchor.get() : null;
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchor != null) {
2070e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            final ViewTreeObserver vto = anchor.getViewTreeObserver();
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.removeOnScrollChangedListener(mOnScrollChangedListener);
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2073e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
2074634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
2075634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        if (anchorRoot != null) {
2076634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2077634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        }
2078634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchor = null;
2080634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchorRoot = null;
2081634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mIsAnchorRootAttached = false;
20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2084634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private void registerForViewTreeChanges(View anchor, int xoff, int yoff, int gravity) {
2085634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        unregisterForViewTreeChanges();
2086e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
2087e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final ViewTreeObserver vto = anchor.getViewTreeObserver();
20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vto != null) {
20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.addOnScrollChangedListener(mOnScrollChangedListener);
20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2092634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchorRoot = anchor.getRootView();
2093634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2094634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2095634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchor = new WeakReference<>(anchor);
2096634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchorRoot = new WeakReference<>(anchorRoot);
2097634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mIsAnchorRootAttached = anchorRoot.isAttachedToWindow();
2098634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorXoff = xoff;
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorYoff = yoff;
210154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mAnchoredGravity = gravity;
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21045435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupDecorView extends FrameLayout {
21058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private TransitionListenerAdapter mPendingExitListener;
21068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
21075435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupDecorView(Context context) {
21085435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
21095435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchKeyEvent(KeyEvent event) {
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
21144ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                if (getKeyDispatcherState() == null) {
21154ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                    return super.dispatchKeyEvent(event);
21164ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                }
21174ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson
21185435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
21195435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
2120b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null) {
2121b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        state.startTracking(event, this);
2122b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
21238d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    return true;
2124b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                } else if (event.getAction() == KeyEvent.ACTION_UP) {
21255435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
2126b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null && state.isTracking(event) && !event.isCanceled()) {
2127b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        dismiss();
2128b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        return true;
2129b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
21308d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                }
21318d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                return super.dispatchKeyEvent(event);
21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
21339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.dispatchKeyEvent(event);
21349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchTouchEvent(MotionEvent ev) {
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
21419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.dispatchTouchEvent(ev);
21439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
21469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onTouchEvent(MotionEvent event) {
21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int x = (int) event.getX();
21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int y = (int) event.getY();
21495435a30ae552391f14009c4459731ae149675b18Alan Viverette
21509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((event.getAction() == MotionEvent.ACTION_DOWN)
21519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
21529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
21549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
21569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
21579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
21589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.onTouchEvent(event);
21599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21618fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
21628fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
21638fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Requests that an enter transition run after the next layout pass.
21648fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
21658fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void requestEnterTransition(Transition transition) {
21668fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final ViewTreeObserver observer = getViewTreeObserver();
21678fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (observer != null && transition != null) {
21688fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final Transition enterTransition = transition.clone();
21698fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
21708fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                // Postpone the enter transition after the first layout pass.
21718fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
21728fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    @Override
21738fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    public void onGlobalLayout() {
21748fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        final ViewTreeObserver observer = getViewTreeObserver();
21758fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        if (observer != null) {
21768fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                            observer.removeOnGlobalLayoutListener(this);
21778fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        }
21788fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
217991098574f90277128415e9593cce1e495cc51465Alan Viverette                        final Rect epicenter = getTransitionEpicenter();
218095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                        enterTransition.setEpicenterCallback(new EpicenterCallback() {
218195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            @Override
218295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            public Rect onGetEpicenter(Transition transition) {
218395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                                return epicenter;
218495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            }
218595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                        });
21868fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        startEnterTransition(enterTransition);
21878fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    }
21888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                });
21898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
21908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
21918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
21928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
21938fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts the pending enter transition, if one is set.
21948fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
21958fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private void startEnterTransition(Transition enterTransition) {
21968fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
21978fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
21988fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
21998fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                enterTransition.addTarget(child);
22008fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
22018fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22028fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22038fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, enterTransition);
22048fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
22068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
22078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.VISIBLE);
22088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22098fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
22108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
22128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts an exit transition immediately.
22138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <p>
22148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <strong>Note:</strong> The transition listener is guaranteed to have
22158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * its {@code onTransitionEnd} method called even if the transition
22168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * never starts; however, it may be called with a {@code null} argument.
22178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
2218634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        public void startExitTransition(Transition transition, final View anchorRoot,
2219634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                final TransitionListener listener) {
22208fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (transition == null) {
22218fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                return;
22228fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22238fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
2224634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // The anchor view's window may go away while we're executing our
2225634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // transition, in which case we need to end the transition
2226634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // immediately and execute the listener to remove the popup.
2227634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2228634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
22298fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // The exit listener MUST be called for cleanup, even if the
22308fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // transition never starts or ends. Stash it for later.
22318fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mPendingExitListener = new TransitionListenerAdapter() {
22328fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                @Override
22338fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                public void onTransitionEnd(Transition transition) {
2234634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
22358fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    listener.onTransitionEnd(transition);
22368fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22378fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    // The listener was called. Our job here is done.
22388fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    mPendingExitListener = null;
22398fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                }
22408fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            };
22418fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22428fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final Transition exitTransition = transition.clone();
22438fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            exitTransition.addListener(mPendingExitListener);
22448fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22458fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
22468fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
22478fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
22488fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                exitTransition.addTarget(child);
22498fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22508fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22518fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, exitTransition);
22528fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22538fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
22548fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
22558fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
22568fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22578fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
22588fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22598fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
22608fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Cancels all pending or current transitions.
22618fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
22628fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void cancelTransitions() {
22638fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.endTransitions(this);
22648fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22658fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (mPendingExitListener != null) {
22668fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                mPendingExitListener.onTransitionEnd(null);
22678fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
22688fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
2269634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2270634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
2271634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                new OnAttachStateChangeListener() {
2272634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    @Override
2273634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    public void onViewAttachedToWindow(View v) {}
2274634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2275634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    @Override
2276634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    public void onViewDetachedFromWindow(View v) {
2277634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        v.removeOnAttachStateChangeListener(this);
2278634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2279634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        TransitionManager.endTransitions(PopupDecorView.this);
2280634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    }
2281634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                };
22825435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
22835435a30ae552391f14009c4459731ae149675b18Alan Viverette
22845435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupBackgroundView extends FrameLayout {
22855435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupBackgroundView(Context context) {
22865435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
22875435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
228875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
228975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        @Override
22905435a30ae552391f14009c4459731ae149675b18Alan Viverette        protected int[] onCreateDrawableState(int extraSpace) {
22915435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (mAboveAnchor) {
22925435a30ae552391f14009c4459731ae149675b18Alan Viverette                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
22935435a30ae552391f14009c4459731ae149675b18Alan Viverette                View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
22945435a30ae552391f14009c4459731ae149675b18Alan Viverette                return drawableState;
229575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            } else {
22965435a30ae552391f14009c4459731ae149675b18Alan Viverette                return super.onCreateDrawableState(extraSpace);
229775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
229875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
22999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2301