PopupWindow.java revision 489c39d2db3be43e34c5ac55e09d8c17a5a04688
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;
572665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carrimport static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
582665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carrimport static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
591e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
611e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
621e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * This class represents a popup window that can be used to display an
631e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * arbitrary view. The popup window is a floating container that appears on top
641e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * of the current activity.
651e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
661e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <a name="Animation"></a>
671e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <h3>Animation</h3>
681e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
691e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * On all versions of Android, popup window enter and exit animations may be
701e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * specified by calling {@link #setAnimationStyle(int)} and passing the
711e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * resource ID for an animation style that defines {@code windowEnterAnimation}
721e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * and {@code windowExitAnimation}. For example, passing
731e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * {@link android.R.style#Animation_Dialog} will give a scale and alpha
741e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * animation.
751e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </br>
761e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * A window animation style may also be specified in the popup window's style
771e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * XML via the {@link android.R.styleable#PopupWindow_popupAnimationStyle popupAnimationStyle}
781e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * attribute.
791e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
801e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * <p>
811e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * Starting with API 23, more complex popup window enter and exit transitions
821e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * may be specified by calling either {@link #setEnterTransition(Transition)}
831e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * or {@link #setExitTransition(Transition)} and passing a  {@link Transition}.
841e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </br>
851e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * Popup enter and exit transitions may also be specified in the popup window's
861e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * style XML via the {@link android.R.styleable#PopupWindow_popupEnterTransition popupEnterTransition}
871e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * and {@link android.R.styleable#PopupWindow_popupExitTransition popupExitTransition}
881e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * attributes, respectively.
891e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * </p>
901e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette *
911e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_overlapAnchor
921e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupAnimationStyle
931e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupBackground
941e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupElevation
951e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
961e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette * @attr ref android.R.styleable#PopupWindow_popupExitTransition
975435a30ae552391f14009c4459731ae149675b18Alan Viverette *
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.AutoCompleteTextView
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.widget.Spinner
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class PopupWindow {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
103e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * input method should be based on the focusability of the popup.  That is
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if it is focusable than it needs to work with the input method, else
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * it doesn't.
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
1095435a30ae552391f14009c4459731ae149675b18Alan Viverette
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
111e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed so that the user can also operate
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the input method while it is shown.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NEEDED = 1;
1175435a30ae552391f14009c4459731ae149675b18Alan Viverette
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
119e29f064383cbc745c8605c707000ab4e16ee0aacRomain Guy     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * work with an input method, regardless of whether it is focusable.  This
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * means that it will always be displayed to use as much space on the
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen as needed, regardless of whether this covers the input method.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int INPUT_METHOD_NOT_NEEDED = 2;
12554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
12654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private static final int DEFAULT_ANCHORED_GRAVITY = Gravity.TOP | Gravity.START;
12754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1285435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
1295435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Default animation style indicating that separate animations should be
1305435a30ae552391f14009c4459731ae149675b18Alan Viverette     * used for top/bottom anchoring states.
1315435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
1325435a30ae552391f14009c4459731ae149675b18Alan Viverette    private static final int ANIMATION_STYLE_DEFAULT = -1;
1335435a30ae552391f14009c4459731ae149675b18Alan Viverette
134f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette    private final int[] mTmpDrawingLocation = new int[2];
135f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette    private final int[] mTmpScreenLocation = new int[2];
1365435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final Rect mTempRect = new Rect();
1375435a30ae552391f14009c4459731ae149675b18Alan Viverette
138448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private Context mContext;
139448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    private WindowManager mWindowManager;
1405435a30ae552391f14009c4459731ae149675b18Alan Viverette
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsShowing;
1428fd949e680c15d397084430d4907c16cedfacddaAlan Viverette    private boolean mIsTransitioningToDismiss;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIsDropdown;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1455435a30ae552391f14009c4459731ae149675b18Alan Viverette    /** View that handles event dispatch and content transitions. */
1465435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView mDecorView;
1475435a30ae552391f14009c4459731ae149675b18Alan Viverette
148697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    /** View that holds the background and may animate during a transition. */
149697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    private View mBackgroundView;
150697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette
151697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette    /** The contents of the popup. May be identical to the background view. */
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mContentView;
1535435a30ae552391f14009c4459731ae149675b18Alan Viverette
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mFocusable;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mInputMethodMode = INPUT_METHOD_FROM_FOCUSABLE;
1567eab094722af54717859b7dcce3cc050f059e00bDianne Hackborn    private int mSoftInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mTouchable = true;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mOutsideTouchable = false;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mClippingEnabled = true;
16046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown    private int mSplitTouchEnabled = -1;
161ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    private boolean mLayoutInScreen;
16256c2d337e02a275397fc9d0460dca90977f199acAdam Powell    private boolean mClipToScreen;
163348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    private boolean mAllowScrollingAnchorParent = true;
1640bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    private boolean mLayoutInsetDecor = false;
165e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    private boolean mNotTouchModal;
166393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecor = true;
167393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    private boolean mAttachedInDecorSet = false;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnTouchListener mTouchInterceptor;
170393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mWidthMode;
172259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mWidth = LayoutParams.WRAP_CONTENT;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastWidth;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mHeightMode;
175259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    private int mHeight = LayoutParams.WRAP_CONTENT;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mLastHeight;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
178ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    private float mElevation;
179ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBackground;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mAboveAnchorBackgroundDrawable;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Drawable mBelowAnchorBackgroundDrawable;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1845435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mEnterTransition;
1855435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition mExitTransition;
18691098574f90277128415e9593cce1e495cc51465Alan Viverette    private Rect mEpicenterBounds;
187560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mAboveAnchor;
189574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
1905435a30ae552391f14009c4459731ae149675b18Alan Viverette
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private OnDismissListener mOnDismissListener;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean mIgnoreCheekPress = false;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1945435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnimationStyle = ANIMATION_STYLE_DEFAULT;
1955435a30ae552391f14009c4459731ae149675b18Alan Viverette
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int[] ABOVE_ANCHOR_STATE_SET = new int[] {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        com.android.internal.R.attr.state_above_anchor
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
200634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
201634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            new OnAttachStateChangeListener() {
202634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                @Override
203634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                public void onViewAttachedToWindow(View v) {}
204634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
205634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                @Override
206634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                public void onViewDetachedFromWindow(View v) {
207634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    mIsAnchorRootAttached = false;
208634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                }
209634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            };
210634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WeakReference<View> mAnchor;
212634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private WeakReference<View> mAnchorRoot;
213634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette    private boolean mIsAnchorRootAttached;
214560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
2155435a30ae552391f14009c4459731ae149675b18Alan Viverette    private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
2165435a30ae552391f14009c4459731ae149675b18Alan Viverette        @Override
2175435a30ae552391f14009c4459731ae149675b18Alan Viverette        public void onScrollChanged() {
2185435a30ae552391f14009c4459731ae149675b18Alan Viverette            final View anchor = mAnchor != null ? mAnchor.get() : null;
2195435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (anchor != null && mDecorView != null) {
2205435a30ae552391f14009c4459731ae149675b18Alan Viverette                final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
2215435a30ae552391f14009c4459731ae149675b18Alan Viverette                        mDecorView.getLayoutParams();
2225435a30ae552391f14009c4459731ae149675b18Alan Viverette
2235435a30ae552391f14009c4459731ae149675b18Alan Viverette                updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
224f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette                        p.width, p.height, mAnchoredGravity));
2255435a30ae552391f14009c4459731ae149675b18Alan Viverette                update(p.x, p.y, -1, -1, true);
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2275435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2285435a30ae552391f14009c4459731ae149675b18Alan Viverette    };
229560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
2305435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorXoff;
2315435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchorYoff;
2325435a30ae552391f14009c4459731ae149675b18Alan Viverette    private int mAnchoredGravity;
233560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette    private boolean mOverlapAnchor;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
235b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private boolean mPopupViewInitialLayoutDirectionInherited;
236b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context) {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, null);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(Context context, AttributeSet attrs) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, attrs, com.android.internal.R.attr.popupWindowStyle);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does provide a background.</p>
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
260617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
261617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
262c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
2635435a30ae552391f14009c4459731ae149675b18Alan Viverette
264c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
265c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Create a new, empty, non focusable popup window of dimension (0,0).</p>
2665435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
267c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>The popup does not provide a background.</p>
268c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
269c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public PopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
27175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
273617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(
274ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                attrs, R.styleable.PopupWindow, defStyleAttr, defStyleRes);
275ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        final Drawable bg = a.getDrawable(R.styleable.PopupWindow_popupBackground);
276ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = a.getDimension(R.styleable.PopupWindow_popupElevation, 0);
277560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
278c3808b5dc7d5873d04e8a0a247b179b2757764baAdam Powell
2795435a30ae552391f14009c4459731ae149675b18Alan Viverette        // Preserve default behavior from Gingerbread. If the animation is
2805435a30ae552391f14009c4459731ae149675b18Alan Viverette        // undefined or explicitly specifies the Gingerbread animation style,
2815435a30ae552391f14009c4459731ae149675b18Alan Viverette        // use a sentinel value.
2825435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupAnimationStyle)) {
2835435a30ae552391f14009c4459731ae149675b18Alan Viverette            final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, 0);
2845435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (animStyle == R.style.Animation_PopupWindow) {
2855435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2865435a30ae552391f14009c4459731ae149675b18Alan Viverette            } else {
2875435a30ae552391f14009c4459731ae149675b18Alan Viverette                mAnimationStyle = animStyle;
2885435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
2895435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
2905435a30ae552391f14009c4459731ae149675b18Alan Viverette            mAnimationStyle = ANIMATION_STYLE_DEFAULT;
2915435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
2925435a30ae552391f14009c4459731ae149675b18Alan Viverette
2935435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition enterTransition = getTransition(a.getResourceId(
2945435a30ae552391f14009c4459731ae149675b18Alan Viverette                R.styleable.PopupWindow_popupEnterTransition, 0));
2955435a30ae552391f14009c4459731ae149675b18Alan Viverette        final Transition exitTransition;
2965435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (a.hasValueOrEmpty(R.styleable.PopupWindow_popupExitTransition)) {
2975435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = getTransition(a.getResourceId(
2985435a30ae552391f14009c4459731ae149675b18Alan Viverette                    R.styleable.PopupWindow_popupExitTransition, 0));
2995435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
3005435a30ae552391f14009c4459731ae149675b18Alan Viverette            exitTransition = enterTransition == null ? null : enterTransition.clone();
3015435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
304ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
3055435a30ae552391f14009c4459731ae149675b18Alan Viverette        setEnterTransition(enterTransition);
3065435a30ae552391f14009c4459731ae149675b18Alan Viverette        setExitTransition(exitTransition);
307ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        setBackgroundDrawable(bg);
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window of dimension (0,0).</p>
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow() {
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, 0, 0);
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window are (0,0).</p>
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView) {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, 0, 0);
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new empty, non focusable popup window. The dimension of the
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window must be passed to this constructor.</p>
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(int width, int height) {
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(null, width, height);
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new non focusable popup window which can display the
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <tt>contentView</tt>. The dimension of the window must be passed to
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this constructor.</p>
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PopupWindow(View contentView, int width, int height) {
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(contentView, width, height, false);
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Create a new popup window which can display the <tt>contentView</tt>.
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The dimension of the window must be passed to this constructor.</p>
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The popup does not provide any background. This should be handled
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the content view.</p>
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the popup's content
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width the popup's width
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height the popup's height
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup can be focused, false otherwise
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
375448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy    public PopupWindow(View contentView, int width, int height, boolean focusable) {
376448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (contentView != null) {
377448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = contentView.getContext();
378448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
379448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
380393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setContentView(contentView);
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setWidth(width);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHeight(height);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setFocusable(focusable);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3871e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
3881e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Sets the enter transition to be used when the popup window is shown.
3891e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
3901e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @param enterTransition the enter transition, or {@code null} to clear
3911e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #getEnterTransition()
3921e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
3931e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
3941e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public void setEnterTransition(@Nullable Transition enterTransition) {
3955435a30ae552391f14009c4459731ae149675b18Alan Viverette        mEnterTransition = enterTransition;
3965435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
3975435a30ae552391f14009c4459731ae149675b18Alan Viverette
3981e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
3991e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Returns the enter transition to be used when the popup window is shown.
4001e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4011e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @return the enter transition, or {@code null} if not set
4021e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #setEnterTransition(Transition)
4031e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupEnterTransition
4041e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4051e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    @Nullable
4061e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public Transition getEnterTransition() {
4071e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette        return mEnterTransition;
4081e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    }
4091e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
4101e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
4111e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Sets the exit transition to be used when the popup window is dismissed.
4121e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4131e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @param exitTransition the exit transition, or {@code null} to clear
4141e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #getExitTransition()
4151e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
4161e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4171e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public void setExitTransition(@Nullable Transition exitTransition) {
4185435a30ae552391f14009c4459731ae149675b18Alan Viverette        mExitTransition = exitTransition;
4195435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
4205435a30ae552391f14009c4459731ae149675b18Alan Viverette
42191098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
4221e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * Returns the exit transition to be used when the popup window is
4231e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * dismissed.
4241e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     *
4251e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @return the exit transition, or {@code null} if not set
4261e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @see #setExitTransition(Transition)
4271e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     * @attr ref android.R.styleable#PopupWindow_popupExitTransition
4281e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette     */
4291e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    @Nullable
4301e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    public Transition getExitTransition() {
4311e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette        return mExitTransition;
4321e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    }
4331e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette
4341e940dc2d165fa6cdedb6945811988502f87ddceAlan Viverette    /**
43591098574f90277128415e9593cce1e495cc51465Alan Viverette     * Sets the bounds used as the epicenter of the enter and exit transitions.
43691098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
43791098574f90277128415e9593cce1e495cc51465Alan Viverette     * Transitions use a point or Rect, referred to as the epicenter, to orient
43891098574f90277128415e9593cce1e495cc51465Alan Viverette     * the direction of travel. For popup windows, the anchor view bounds are
43991098574f90277128415e9593cce1e495cc51465Alan Viverette     * used as the default epicenter.
44091098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
44191098574f90277128415e9593cce1e495cc51465Alan Viverette     * See {@link Transition#setEpicenterCallback(EpicenterCallback)} for more
44291098574f90277128415e9593cce1e495cc51465Alan Viverette     * information about how transition epicenters.
44391098574f90277128415e9593cce1e495cc51465Alan Viverette     *
44491098574f90277128415e9593cce1e495cc51465Alan Viverette     * @param bounds the epicenter bounds relative to the anchor view, or
44591098574f90277128415e9593cce1e495cc51465Alan Viverette     *               {@code null} to use the default epicenter
44691098574f90277128415e9593cce1e495cc51465Alan Viverette     * @see #getTransitionEpicenter()
44791098574f90277128415e9593cce1e495cc51465Alan Viverette     * @hide
44891098574f90277128415e9593cce1e495cc51465Alan Viverette     */
44991098574f90277128415e9593cce1e495cc51465Alan Viverette    public void setEpicenterBounds(Rect bounds) {
45091098574f90277128415e9593cce1e495cc51465Alan Viverette        mEpicenterBounds = bounds;
45191098574f90277128415e9593cce1e495cc51465Alan Viverette    }
45291098574f90277128415e9593cce1e495cc51465Alan Viverette
4535435a30ae552391f14009c4459731ae149675b18Alan Viverette    private Transition getTransition(int resId) {
4545435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (resId != 0 && resId != R.transition.no_transition) {
4555435a30ae552391f14009c4459731ae149675b18Alan Viverette            final TransitionInflater inflater = TransitionInflater.from(mContext);
4565435a30ae552391f14009c4459731ae149675b18Alan Viverette            final Transition transition = inflater.inflateTransition(resId);
4575435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (transition != null) {
4585435a30ae552391f14009c4459731ae149675b18Alan Viverette                final boolean isEmpty = transition instanceof TransitionSet
4595435a30ae552391f14009c4459731ae149675b18Alan Viverette                        && ((TransitionSet) transition).getTransitionCount() == 0;
4605435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (!isEmpty) {
4615435a30ae552391f14009c4459731ae149675b18Alan Viverette                    return transition;
4625435a30ae552391f14009c4459731ae149675b18Alan Viverette                }
4635435a30ae552391f14009c4459731ae149675b18Alan Viverette            }
4645435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
4655435a30ae552391f14009c4459731ae149675b18Alan Viverette        return null;
4665435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
4675435a30ae552391f14009c4459731ae149675b18Alan Viverette
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
469ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Return the drawable used as the popup window's background.
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
471ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the background drawable or {@code null} if not set
472ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setBackgroundDrawable(Drawable)
473ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable getBackground() {
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mBackground;
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
480ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the background drawable for this popup window. The background
481ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * can be set to {@code null}.
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param background the popup's background
484ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getBackground()
485ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupBackground
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setBackgroundDrawable(Drawable background) {
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mBackground = background;
489ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
490ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // If this is a StateListDrawable, try to find and store the drawable to be
491ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed above its anchor view, and the one to be
492ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // used when the drop-down is placed below its anchor view. We extract
493ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // the drawables ourselves to work around a problem with using refreshDrawableState
494ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // that it will take into account the padding of all drawables specified in a
495ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // StateListDrawable, thus adding superfluous padding to drop-down views.
496ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        //
497ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // We assume a StateListDrawable will have a drawable for ABOVE_ANCHOR_STATE_SET and
498ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        // at least one other drawable, intended for the 'below-anchor state'.
499ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        if (mBackground instanceof StateListDrawable) {
500ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            StateListDrawable stateList = (StateListDrawable) mBackground;
501ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
502ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Find the above-anchor view - this one's easy, it should be labeled as such.
503ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int aboveAnchorStateIndex = stateList.getStateDrawableIndex(ABOVE_ANCHOR_STATE_SET);
504ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
505ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Now, for the below-anchor view, look for any other drawable specified in the
506ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // StateListDrawable which is not for the above-anchor state and use that.
507ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int count = stateList.getStateCount();
508ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            int belowAnchorStateIndex = -1;
509ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            for (int i = 0; i < count; i++) {
510ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                if (i != aboveAnchorStateIndex) {
511ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    belowAnchorStateIndex = i;
512ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                    break;
513ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                }
514ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
515ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette
516ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // Store the drawables we found, if we found them. Otherwise, set them both
517ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            // to null so that we'll just use refreshDrawableState.
518ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            if (aboveAnchorStateIndex != -1 && belowAnchorStateIndex != -1) {
519ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = stateList.getStateDrawable(aboveAnchorStateIndex);
520ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = stateList.getStateDrawable(belowAnchorStateIndex);
521ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            } else {
522ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mBelowAnchorBackgroundDrawable = null;
523ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette                mAboveAnchorBackgroundDrawable = null;
524ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette            }
525ce8c358712414e4fa98e4504e6a1b8ad36d37c6cAlan Viverette        }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
529ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @return the elevation for this popup window in pixels
530ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #setElevation(float)
531ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
532ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
533ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public float getElevation() {
534ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        return mElevation;
535ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
536ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
537ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
538ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * Specifies the elevation for this popup window.
539ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     *
540ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @param elevation the popup's elevation in pixels
541ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @see #getElevation()
542ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     * @attr ref android.R.styleable#PopupWindow_popupElevation
543ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette     */
544ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    public void setElevation(float elevation) {
545ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette        mElevation = elevation;
546ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    }
547ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
548ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette    /**
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the animation style to use the popup appears and disappears</p>
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the animation style to use the popup appears and disappears
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getAnimationStyle() {
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
556393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
55854ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * Set the flag on popup to ignore cheek press events; by default this flag
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is set to false
56054ec76d81ac38284caa6d00ad5f2d2207206b9ceShuhrat Dehkanov     * which means the popup will not ignore cheek press dispatch events.
5615435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
565393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setIgnoreCheekPress() {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIgnoreCheekPress = true;
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5715435a30ae552391f14009c4459731ae149675b18Alan Viverette
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the animation style resource for this popup.</p>
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param animationStyle animation style to use when the popup appears
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      and disappears.  Set to -1 for the default animation, 0 for no
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      animation, or a resource identifier for an explicit animation.
5835435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAnimationStyle(int animationStyle) {
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnimationStyle = animationStyle;
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5895435a30ae552391f14009c4459731ae149675b18Alan Viverette
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Return the view used as the content of the popup window.</p>
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return a {@link android.view.View} representing the popup's content
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setContentView(android.view.View)
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public View getContentView() {
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mContentView;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the popup's content. The content is represented by an instance
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of {@link android.view.View}.</p>
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
60581f08086b44a117097960195d2c9072e29644962Gilles Debunne     * <p>This method has no effect if called when the popup is showing.</p>
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param contentView the new content for the popup
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getContentView()
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setContentView(View contentView) {
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing()) {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContentView = contentView;
618448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
6190c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext == null && mContentView != null) {
620448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mContext = mContentView.getContext();
621448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
622448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
6230c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mWindowManager == null && mContentView != null) {
624448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
625448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
626393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
627393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // Setting the default for attachedInDecor based on SDK version here
628393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // instead of in the constructor since we might not have the context
629393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // object in the constructor. We only want to set default here if the
630393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        // app hasn't already set the attachedInDecor.
631393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mContext != null && !mAttachedInDecorSet) {
632393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // Attach popup window in decor frame of parent window by default for
633393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current
634393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            // behavior of not attaching to decor frame for older SDKs.
635393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale            setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion
636393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale                    >= Build.VERSION_CODES.LOLLIPOP_MR1);
637393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
638393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set a callback for all touch events being dispatched to the popup
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window.
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchInterceptor(OnTouchListener l) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchInterceptor = l;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
648393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether the popup window can grab the focus.</p>
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is focusable, false otherwise
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setFocusable(boolean)
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isFocusable() {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mFocusable;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the focusability of the popup window. When focusable, the
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will grab the focus from the current focused widget if the popup
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * contains a focusable {@link android.view.View}.  By default a popup
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is not focusable.</p>
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param focusable true if the popup should grab focus, false otherwise.
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isFocusable()
6735435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setFocusable(boolean focusable) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFocusable = focusable;
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return the current value in {@link #setInputMethodMode(int)}.
6825435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setInputMethodMode(int)
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getInputMethodMode() {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInputMethodMode;
6875435a30ae552391f14009c4459731ae149675b18Alan Viverette
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6895435a30ae552391f14009c4459731ae149675b18Alan Viverette
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control how the popup operates with an input method: one of
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #INPUT_METHOD_NOT_NEEDED}.
6945435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
6985435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getInputMethodMode()
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethodMode(int mode) {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputMethodMode = mode;
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
705374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
706374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
707374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Sets the operating mode for the soft input area.
708374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
709374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @param mode The desired mode, see
710374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
711374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *        for the full list
712374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
713374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
714374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #getSoftInputMode()
715374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
716374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public void setSoftInputMode(int mode) {
717374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        mSoftInputMode = mode;
718374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
719374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy
720374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    /**
721374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * Returns the current value in {@link #setSoftInputMode(int)}.
722374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     *
723374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see #setSoftInputMode(int)
724374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     * @see android.view.WindowManager.LayoutParams#softInputMode
725374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy     */
726374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    public int getSoftInputMode() {
727374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy        return mSoftInputMode;
728374aaaed32daa8482d98ec16988b2b51547f035dRomain Guy    }
7295435a30ae552391f14009c4459731ae149675b18Alan Viverette
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window receives touch events.</p>
7325435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is touchable, false otherwise
7345435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setTouchable(boolean)
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isTouchable() {
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mTouchable;
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Changes the touchability of the popup window. When touchable, the
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window will receive touch events, otherwise touch events will go to the
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window below it. By default the window is touchable.</p>
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive touch events, false otherwise
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isTouchable()
7535435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setTouchable(boolean touchable) {
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mTouchable = touchable;
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether the popup window will be informed of touch events
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * outside of its window.</p>
7635435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is outside touchable, false otherwise
7655435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setOutsideTouchable(boolean)
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isOutsideTouchable() {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOutsideTouchable;
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Controls whether the pop-up will be informed of touch events outside
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of its window.  This only makes sense for pop-ups that are touchable
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * but not focusable, which means touches outside of the window will
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be delivered to the window behind.  The default is false.</p>
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param touchable true if the popup should receive outside
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * touch events, false otherwise
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isOutsideTouchable()
7865435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOutsideTouchable(boolean touchable) {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOutsideTouchable = touchable;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether clipping of the popup window is enabled.</p>
7955435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the clipping is enabled, false otherwise
7975435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setClippingEnabled(boolean)
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isClippingEnabled() {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mClippingEnabled;
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Allows the popup window to extend beyond the bounds of the screen. By default the
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window is clipped to the screen boundaries. Setting this to false will allow windows to be
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * accurately positioned.</p>
8085435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown or through a manual call to one of
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the {@link #update()} methods.</p>
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param enabled false if the window should be allowed to extend outside of the screen
8145435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isClippingEnabled()
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #update()
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setClippingEnabled(boolean enabled) {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mClippingEnabled = enabled;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
82356c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * Clip this popup window to the screen, but not to the containing window.
82456c2d337e02a275397fc9d0460dca90977f199acAdam Powell     *
82556c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @param enabled True to clip to the screen.
82656c2d337e02a275397fc9d0460dca90977f199acAdam Powell     * @hide
82756c2d337e02a275397fc9d0460dca90977f199acAdam Powell     */
82856c2d337e02a275397fc9d0460dca90977f199acAdam Powell    public void setClipToScreenEnabled(boolean enabled) {
82956c2d337e02a275397fc9d0460dca90977f199acAdam Powell        mClipToScreen = enabled;
83056c2d337e02a275397fc9d0460dca90977f199acAdam Powell    }
831348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell
832348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    /**
833348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * Allow PopupWindow to scroll the anchor's parent to provide more room
834348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * for the popup. Enabled by default.
835348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     *
836348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * @param enabled True to scroll the anchor's parent when more room is desired by the popup.
837348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     */
838348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    void setAllowScrollingAnchorParent(boolean enabled) {
839348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mAllowScrollingAnchorParent = enabled;
840348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    }
8415435a30ae552391f14009c4459731ae149675b18Alan Viverette
84256c2d337e02a275397fc9d0460dca90977f199acAdam Powell    /**
84301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Indicates whether the popup window supports splitting touches.</p>
8445435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
84501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @return true if the touch splitting is enabled, false otherwise
8465435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
84701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #setSplitTouchEnabled(boolean)
84801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
84901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public boolean isSplitTouchEnabled() {
85046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (mSplitTouchEnabled < 0 && mContext != null) {
85146e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown            return mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
85246e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        }
85346e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        return mSplitTouchEnabled == 1;
85401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
85501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
85601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
85701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * <p>Allows the popup window to split touches across other windows that also
85846e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * support split touch.  When this flag is false, the first pointer
85901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * that goes down determines the window to which all subsequent touches
86046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown     * go until all pointers go up.  When this flag is true, each pointer
86101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * (not necessarily the first) that goes down determines the window
86201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to which all subsequent touches of that pointer will go until that
86301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * pointer goes up thereby enabling touches with multiple pointers
86401ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * to be split across multiple windows.</p>
86501ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     *
86601ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @param enabled true if the split touches should be enabled, false otherwise
86701ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     * @see #isSplitTouchEnabled()
86801ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown     */
86901ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    public void setSplitTouchEnabled(boolean enabled) {
87046e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        mSplitTouchEnabled = enabled ? 1 : 0;
87101ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    }
87201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown
87301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown    /**
874ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Indicates whether the popup window will be forced into using absolute screen coordinates
875ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * for positioning.</p>
876ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
877ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @return true if the window will always be positioned in screen coordinates.
878ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
879ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
880ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public boolean isLayoutInScreenEnabled() {
881ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        return mLayoutInScreen;
882ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
883ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
884ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
885ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * <p>Allows the popup window to force the flag
886ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior.
887ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * This will cause the popup to be positioned in absolute screen coordinates.</p>
888ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     *
889ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @param enabled true if the popup should always be positioned in screen coordinates
890ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     * @hide
891ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell     */
892ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    public void setLayoutInScreenEnabled(boolean enabled) {
893ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        mLayoutInScreen = enabled;
894ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    }
895ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell
896ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell    /**
897393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>Indicates whether the popup window will be attached in the decor frame of its parent
898393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * window.
899393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
900393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @return true if the window will be attached to the decor frame of its parent window.
901393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
902393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see #setAttachedInDecor(boolean)
903393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
904393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
905393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public boolean isAttachedInDecor() {
906393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        return mAttachedInDecor;
907393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
908393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
909393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
910393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>This will attach the popup window to the decor frame of the parent window to avoid
911393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * overlaping with screen decorations like the navigation bar. Overrides the default behavior of
912393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}.
913393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
914393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or
915393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * greater and cleared on lesser SDK versions.
916393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
917393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @param enabled true if the popup should be attached to the decor frame of its parent window.
918393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     *
919393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
920393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale     */
921393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    public void setAttachedInDecor(boolean enabled) {
922393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecor = enabled;
923393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        mAttachedInDecorSet = true;
924393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    }
925393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
926393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale    /**
9270bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * Allows the popup window to force the flag
9280bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
9290bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * This will cause the popup to inset its content to account for system windows overlaying
9300bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * the screen, such as the status bar.
9310bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
9320bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * <p>This will often be combined with {@link #setLayoutInScreenEnabled(boolean)}.
9330bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *
9340bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @param enabled true if the popup's views should inset content to account for system windows,
9350bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     *                the way that decor views behave for full-screen windows.
9360bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     * @hide
9370bd1d0a15294345bf88b20df28466907f982cec7Adam Powell     */
9380bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    public void setLayoutInsetDecor(boolean enabled) {
9390bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        mLayoutInsetDecor = enabled;
9400bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    }
9410bd1d0a15294345bf88b20df28466907f982cec7Adam Powell
9420bd1d0a15294345bf88b20df28466907f982cec7Adam Powell    /**
94380ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * Set the layout type for this window.
94480ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * <p>
94580ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * See {@link WindowManager.LayoutParams#type} for possible values.
946574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     *
947574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     * @param layoutType Layout type for this window.
94836344a90c226c90243e4e02bfb13589e120431ddChris Banes     *
94936344a90c226c90243e4e02bfb13589e120431ddChris Banes     * @see WindowManager.LayoutParams#type
950574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
951574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public void setWindowLayoutType(int layoutType) {
952574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        mWindowLayoutType = layoutType;
953574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
954574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
955574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
95636344a90c226c90243e4e02bfb13589e120431ddChris Banes     * Returns the layout type for this window.
95736344a90c226c90243e4e02bfb13589e120431ddChris Banes     *
95836344a90c226c90243e4e02bfb13589e120431ddChris Banes     * @see #setWindowLayoutType(int)
959574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell     */
960574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    public int getWindowLayoutType() {
961574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell        return mWindowLayoutType;
962574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    }
963574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell
964574b37ecc20a5358cb6147dae6d633385467ab55Adam Powell    /**
965e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * Set whether this window is touch modal or if outside touches will be sent to
966e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * other windows behind it.
967e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     * @hide
968e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell     */
969e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    public void setTouchModal(boolean touchModal) {
970e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        mNotTouchModal = !touchModal;
971e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    }
972e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell
973e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell    /**
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Change the width and height measure specs that are given to the
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * window manager by the popup.  By default these are 0, meaning that
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the current width or height is requested as an explicit size from
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the window manager.  You can supply
9785435a30ae552391f14009c4459731ae149675b18Alan Viverette     * {@link ViewGroup.LayoutParams#WRAP_CONTENT} or
979980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT} to have that measure
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * spec supplied instead, replacing the absolute width and height that
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * has been set in the popup.</p>
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>If the popup is showing, calling this method will take effect only
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the next time the popup is shown.</p>
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param widthSpec an explicit width measure spec mode, either
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
988980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * width.
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param heightSpec an explicit height measure spec mode, either
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link ViewGroup.LayoutParams#WRAP_CONTENT},
992980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy     * {@link ViewGroup.LayoutParams#MATCH_PARENT}, or 0 to use the absolute
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * height.
994259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *
995259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @deprecated Use {@link #setWidth(int)} and {@link #setHeight(int)}.
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
997259c2840691a79634ffd8f63291ec21c21819542Alan Viverette    @Deprecated
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWindowLayoutMode(int widthSpec, int heightSpec) {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidthMode = widthSpec;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeightMode = heightSpec;
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10025435a30ae552391f14009c4459731ae149675b18Alan Viverette
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1004c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * Returns the popup's requested height. May be a layout constant such as
1005c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
1006c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * <p>
1007c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * The actual size of the popup may depend on other factors such as
1008c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * clipping and window layout.
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1010c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @return the popup height in pixels or a layout constant
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHeight(int)
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getHeight() {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mHeight;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1018c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * Sets the popup's requested height. May be a layout constant such as
1019c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
1020c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * <p>
1021c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * The actual size of the popup may depend on other factors such as
1022c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * clipping and window layout.
1023259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1024259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
1025259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1027c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the popup height in pixels or a layout constant
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getHeight()
10295435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #isShowing()
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHeight(int height) {
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeight = height;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1036c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * Returns the popup's requested width. May be a layout constant such as
1037c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
1038c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * <p>
1039c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * The actual size of the popup may depend on other factors such as
1040c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * clipping and window layout.
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1042c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @return the popup width in pixels or a layout constant
10435435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #setWidth(int)
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWidth() {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWidth;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1050c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * Sets the popup's requested width. May be a layout constant such as
1051c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * {@link LayoutParams#WRAP_CONTENT} or {@link LayoutParams#MATCH_PARENT}.
1052c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * <p>
1053c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * The actual size of the popup may depend on other factors such as
1054c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * clipping and window layout.
1055259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1056259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the popup is showing, calling this method will take effect the next
1057259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * time the popup is shown.
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1059c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the popup width in pixels or a layout constant
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #getWidth()
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #isShowing()
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setWidth(int width) {
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidth = width;
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
106875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Sets whether the popup window should overlap its anchor view when
106975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
107075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
107175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the popup is showing, calling this method will take effect only
107275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the next time the popup is shown.
107375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
107475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @param overlapAnchor Whether the popup should overlap its anchor.
107575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
107675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #getOverlapAnchor()
107775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #isShowing()
107875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
107975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public void setOverlapAnchor(boolean overlapAnchor) {
108075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        mOverlapAnchor = overlapAnchor;
108175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
108275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
108375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
108475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Returns whether the popup window should overlap its anchor view when
108575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * displayed as a drop-down.
108675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
108775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @return Whether the popup should overlap its anchor.
108875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     *
108975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * @see #setOverlapAnchor(boolean)
109075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     */
109175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    public boolean getOverlapAnchor() {
109275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        return mOverlapAnchor;
109375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    }
109475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette
109575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette    /**
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicate whether this popup window is showing on screen.</p>
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is showing, false otherwise
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isShowing() {
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsShowing;
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Display the content view in a popup window at the specified location. If the popup window
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams}
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for more information on how gravity and the x and y parameters are related. Specifying
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>Gravity.LEFT | Gravity.TOP</code>.
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </p>
11125435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity the gravity which controls the placement of the popup window
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the popup's x location offset
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the popup's y location offset
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAtLocation(View parent, int gravity, int x, int y) {
11198ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell        showAtLocation(parent.getWindowToken(), gravity, x, y);
11208ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    }
11218ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell
11228ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    /**
11238ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * Display the content view in a popup window at the specified location.
11248ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
11258ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param token Window token to use for creating the new window
11268ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param gravity the gravity which controls the placement of the popup window
11278ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param x the popup's x location offset
11288ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @param y the popup's y location offset
11298ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *
11308ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     * @hide Internal use only. Applications should use
11318ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     *       {@link #showAtLocation(View, int, int, int)} instead.
11328ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell     */
11338ee6d7c20e7767c2f61f8db9a99d01e0a05f3842Adam Powell    public void showAtLocation(IBinder token, int gravity, int x, int y) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1138e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1139e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1140f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        detachFromAnchor();
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = false;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1145e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(token);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
1147e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1148e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Only override the default if some gravity was specified.
1149e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (gravity != Gravity.NO_GRAVITY) {
1150e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.gravity = gravity;
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1152e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.x = x;
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.y = y;
1155e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
116075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view. If there is not enough room on screen to show
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup in its entirety, this method tries to find a parent scroll
116375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view to scroll. If no parent scroll view can be scrolled, the
116475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * bottom-left corner of the popup is pinned at the top left corner of the
116575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * anchor view.
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor) {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        showAsDropDown(anchor, 0, 0);
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
117675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Display the content view in a popup window anchored to the bottom-left
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corner of the anchor view offset by the specified x and y coordinates.
117875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
117975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
118075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * scroll view can be scrolled, the bottom-left corner of the popup is
118175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * pinned at the top left corner of the anchor view.
118275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
118375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
118475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which to pin the popup window
118754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
118854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #dismiss()
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showAsDropDown(View anchor, int xoff, int yoff) {
119354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        showAsDropDown(anchor, xoff, yoff, DEFAULT_ANCHORED_GRAVITY);
119454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
119554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
119654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    /**
119775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * Displays the content view in a popup window anchored to the corner of
119875d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * another view. The window is positioned according to the specified
119975d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * gravity and offset by the specified x and y coordinates.
120075d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
120175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If there is not enough room on screen to show the popup in its entirety,
120275d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * this method tries to find a parent scroll view to scroll. If no parent
120375d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * view can be scrolled, the specified vertical gravity will be ignored and
120475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * the popup will anchor itself such that it is visible.
120575d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * <p>
120675d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * If the view later scrolls to move <code>anchor</code> to a different
120775d837954c3673647e3a899f03cd56c0892066e0Alan Viverette     * location, the popup will be moved correspondingly.
120854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
120954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param anchor the view on which to pin the popup window
121054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param xoff A horizontal offset from the anchor in pixels
121154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param yoff A vertical offset from the anchor in pixels
121254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param gravity Alignment of the popup relative to the anchor
121354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
121454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @see #dismiss()
121554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     */
121654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isShowing() || mContentView == null) {
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1221e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        TransitionManager.endTransitions(mDecorView);
1222e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1223f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        attachToAnchor(anchor, xoff, yoff, gravity);
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsShowing = true;
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsDropdown = true;
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1228e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        preparePopup(p);
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1231f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
1232f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette                p.width, p.height, gravity);
1233e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        updateAboveAnchor(aboveAnchor);
1234396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver        p.accessibilityIdOfAnchor = (anchor != null) ? anchor.getAccessibilityViewId() : -1;
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invokePopup(p);
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12393e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    private void updateAboveAnchor(boolean aboveAnchor) {
12403e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        if (aboveAnchor != mAboveAnchor) {
12413e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            mAboveAnchor = aboveAnchor;
12423e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
1243697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            if (mBackground != null && mBackgroundView != null) {
1244697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // If the background drawable provided was a StateListDrawable
1245697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // with above-anchor and below-anchor states, use those.
1246697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                // Otherwise, rely on refreshDrawableState to do the job.
12473e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                if (mAboveAnchorBackgroundDrawable != null) {
12483e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    if (mAboveAnchor) {
1249697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                        mBackgroundView.setBackground(mAboveAnchorBackgroundDrawable);
12503e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    } else {
1251697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                        mBackgroundView.setBackground(mBelowAnchorBackgroundDrawable);
12523e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                    }
12533e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                } else {
1254697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette                    mBackgroundView.refreshDrawableState();
12553e141685003939a9addce21ba2492ea3a8aebee6Romain Guy                }
12563e141685003939a9addce21ba2492ea3a8aebee6Romain Guy            }
12573e141685003939a9addce21ba2492ea3a8aebee6Romain Guy        }
12583e141685003939a9addce21ba2492ea3a8aebee6Romain Guy    }
12593e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Indicates whether the popup is showing above (the y coordinate of the popup's bottom
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is less than the y coordinate of the anchor) or below the anchor view (the y coordinate
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the popup is greater than y coordinate of the anchor's bottom).
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The value returned
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by this method is meaningful only after {@link #showAsDropDown(android.view.View)}
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * or {@link #showAsDropDown(android.view.View, int, int)} was invoked.
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return True if this popup is showing above the anchor view, false otherwise.
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isAboveAnchor() {
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAboveAnchor;
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1276e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * Prepare the popup by embedding it into a new ViewGroup if the background
1277e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * drawable is not null. If embedding is required, the layout parameters'
1278e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette     * height is modified to take into account the background's padding.
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void preparePopup(WindowManager.LayoutParams p) {
1283448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        if (mContentView == null || mContext == null || mWindowManager == null) {
1284448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy            throw new IllegalStateException("You must specify a valid content view by "
1285448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy                    + "calling setContentView() before attempting to show the popup.");
1286448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy        }
1287448ecf5a94bb8778c677f00dedd33b26ea7683e8Romain Guy
12888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // The old decor view may be transitioning out. Make sure it finishes
12898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // and cleans up before we try to create another one.
12908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (mDecorView != null) {
12918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mDecorView.cancelTransitions();
12928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
12938fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
12945435a30ae552391f14009c4459731ae149675b18Alan Viverette        // When a background is available, we embed the content view within
12955435a30ae552391f14009c4459731ae149675b18Alan Viverette        // another view that owns the background drawable.
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
1297697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView = createBackgroundView(mContentView);
1298697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView.setBackground(mBackground);
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1300697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette            mBackgroundView = mContentView;
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1302ccb11e183763db5cbaca96abe461adf480ed8e44Alan Viverette
1303697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mDecorView = createDecorView(mBackgroundView);
13045435a30ae552391f14009c4459731ae149675b18Alan Viverette
13055435a30ae552391f14009c4459731ae149675b18Alan Viverette        // The background owner should be elevated so that it casts a shadow.
1306697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mBackgroundView.setElevation(mElevation);
13075435a30ae552391f14009c4459731ae149675b18Alan Viverette
13085435a30ae552391f14009c4459731ae149675b18Alan Viverette        // We may wrap that in another view, so we'll need to manually specify
13095435a30ae552391f14009c4459731ae149675b18Alan Viverette        // the surface insets.
1310246c209e4fe704c0745224be0ab05225e8431d11Wale Ogunwale        p.setSurfaceInsets(mBackgroundView, true /*manual*/, true /*preservePrevious*/);
13115435a30ae552391f14009c4459731ae149675b18Alan Viverette
1312b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        mPopupViewInitialLayoutDirectionInherited =
13135435a30ae552391f14009c4459731ae149675b18Alan Viverette                (mContentView.getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT);
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13175435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a PopupViewContainer.
13185435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
13195435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
13205435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a PopupViewContainer that wraps the content view
13215435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
13225435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupBackgroundView createBackgroundView(View contentView) {
13235435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
13245435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
13252665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr        if (layoutParams != null && layoutParams.height == WRAP_CONTENT) {
13262665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr            height = WRAP_CONTENT;
13275435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
13282665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr            height = MATCH_PARENT;
13295435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
13305435a30ae552391f14009c4459731ae149675b18Alan Viverette
13315435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView backgroundView = new PopupBackgroundView(mContext);
13325435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupBackgroundView.LayoutParams listParams = new PopupBackgroundView.LayoutParams(
13332665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr                MATCH_PARENT, height);
13345435a30ae552391f14009c4459731ae149675b18Alan Viverette        backgroundView.addView(contentView, listParams);
13355435a30ae552391f14009c4459731ae149675b18Alan Viverette
13365435a30ae552391f14009c4459731ae149675b18Alan Viverette        return backgroundView;
13375435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
13385435a30ae552391f14009c4459731ae149675b18Alan Viverette
13395435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
13405435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Wraps a content view in a FrameLayout.
13415435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
13425435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @param contentView the content view to wrap
13435435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @return a FrameLayout that wraps the content view
13445435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
13455435a30ae552391f14009c4459731ae149675b18Alan Viverette    private PopupDecorView createDecorView(View contentView) {
13465435a30ae552391f14009c4459731ae149675b18Alan Viverette        final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
13475435a30ae552391f14009c4459731ae149675b18Alan Viverette        final int height;
13482665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr        if (layoutParams != null && layoutParams.height == WRAP_CONTENT) {
13492665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr            height = WRAP_CONTENT;
13505435a30ae552391f14009c4459731ae149675b18Alan Viverette        } else {
13512665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr            height = MATCH_PARENT;
13525435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
13535435a30ae552391f14009c4459731ae149675b18Alan Viverette
13545435a30ae552391f14009c4459731ae149675b18Alan Viverette        final PopupDecorView decorView = new PopupDecorView(mContext);
13552665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr        decorView.addView(contentView, MATCH_PARENT, height);
13565435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipChildren(false);
13575435a30ae552391f14009c4459731ae149675b18Alan Viverette        decorView.setClipToPadding(false);
13585435a30ae552391f14009c4459731ae149675b18Alan Viverette
13595435a30ae552391f14009c4459731ae149675b18Alan Viverette        return decorView;
13605435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
13615435a30ae552391f14009c4459731ae149675b18Alan Viverette
13625435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Invoke the popup window by adding the content view to the window
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * manager.</p>
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The content view must be non-null when this method is invoked.</p>
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param p the layout parameters of the popup's content view
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void invokePopup(WindowManager.LayoutParams p) {
13710c0b768e1514280812321854db6dfba723c3d169Romain Guy        if (mContext != null) {
13720c0b768e1514280812321854db6dfba723c3d169Romain Guy            p.packageName = mContext.getPackageName();
13730c0b768e1514280812321854db6dfba723c3d169Romain Guy        }
13745435a30ae552391f14009c4459731ae149675b18Alan Viverette
13758fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
13768fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.setFitsSystemWindows(mLayoutInsetDecor);
13775435a30ae552391f14009c4459731ae149675b18Alan Viverette
13788fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        setLayoutDirectionFromAnchor();
13795435a30ae552391f14009c4459731ae149675b18Alan Viverette
13808fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mWindowManager.addView(decorView, p);
138195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
138295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        if (mEnterTransition != null) {
138395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            decorView.requestEnterTransition(mEnterTransition);
138495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        }
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1387b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    private void setLayoutDirectionFromAnchor() {
1388b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        if (mAnchor != null) {
1389b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            View anchor = mAnchor.get();
1390b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            if (anchor != null && mPopupViewInitialLayoutDirectionInherited) {
13915435a30ae552391f14009c4459731ae149675b18Alan Viverette                mDecorView.setLayoutDirection(anchor.getLayoutDirection());
1392b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            }
1393b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio        }
1394b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio    }
1395b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
1396489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr    private int computeGravity() {
1397489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        int gravity = Gravity.START | Gravity.TOP;
1398489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        if (mClipToScreen || mClippingEnabled) {
1399489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr            gravity |= Gravity.DISPLAY_CLIP_VERTICAL | Gravity.DISPLAY_CLIP_HORIZONTAL;
1400489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        }
1401489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        return gravity;
1402489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr    }
1403489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Generate the layout parameters for the popup window.</p>
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param token the window token used to bind the popup's window
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the layout parameters to pass to the window manager
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1411e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette    private WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
1412e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();
1413e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1414e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // These gravity settings put the view at the top left corner of the
1415e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // screen. The view is then positioned to the appropriate location by
1416e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // setting the x and y offsets to match the anchor's bottom-left
1417e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // corner.
1418489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        p.gravity = computeGravity();
1419e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.flags = computeFlags(p.flags);
1420e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.type = mWindowLayoutType;
1421e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.token = token;
1422e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.softInputMode = mSoftInputMode;
1423e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        p.windowAnimations = computeAnimationResource();
1424e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = mBackground.getOpacity();
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.format = PixelFormat.TRANSLUCENT;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1430e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1431e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mHeightMode < 0) {
1432e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeightMode;
1433e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1434e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.height = mLastHeight = mHeight;
1435e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1436e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
1437e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        if (mWidthMode < 0) {
1438e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidthMode;
1439e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
1440e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            p.width = mLastWidth = mWidth;
1441e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
1442e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
14438216eb2221ad5ad6615d3966f43844268756f3c8Wale Ogunwale        p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH
14448216eb2221ad5ad6615d3966f43844268756f3c8Wale Ogunwale                | PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
1445a1eb439eee65138280c560f96e2a6896f9c9112cRobert Carr
1446e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        // Used for debugging.
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return p;
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeFlags(int curFlags) {
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        curFlags &= ~(
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES |
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE |
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
1459ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
1460ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell                WindowManager.LayoutParams.FLAG_SPLIT_TOUCH);
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if(mIgnoreCheekPress) {
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mFocusable) {
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mInputMethodMode == INPUT_METHOD_NEEDED) {
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mInputMethodMode == INPUT_METHOD_NOT_NEEDED) {
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mTouchable) {
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1475c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project        if (mOutsideTouchable) {
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1478cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        if (!mClippingEnabled || mClipToScreen) {
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
148146e75294d540fe807d78aec2582ae02cc38c7d42Jeff Brown        if (isSplitTouchEnabled()) {
148201ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown            curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
148301ce2e9eee41cc0c24b0d16465710a28ea337d5dJeff Brown        }
1484ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        if (mLayoutInScreen) {
1485ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
1486ba0a2c383ffe4be1fe33a5aa57bc3148c4fd0b7cAdam Powell        }
14870bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        if (mLayoutInsetDecor) {
14880bd1d0a15294345bf88b20df28466907f982cec7Adam Powell            curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
14890bd1d0a15294345bf88b20df28466907f982cec7Adam Powell        }
1490e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        if (mNotTouchModal) {
1491e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell            curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
1492e0b6cd14ac116006e26dac6898a332fa90f1f49cAdam Powell        }
1493393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        if (mAttachedInDecor) {
1494393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale          curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
1495393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale        }
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return curFlags;
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1498393b1c1e88cbdd0f65c8f217c495dbbe8de9125dWale Ogunwale
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int computeAnimationResource() {
15005435a30ae552391f14009c4459731ae149675b18Alan Viverette        if (mAnimationStyle == ANIMATION_STYLE_DEFAULT) {
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mIsDropdown) {
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mAboveAnchor
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ? com.android.internal.R.style.Animation_DropDownUp
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        : com.android.internal.R.style.Animation_DropDownDown;
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAnimationStyle;
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1510560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1512560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * Positions the popup window on screen. When the popup window is too tall
1513560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to fit under the anchor, a parent scroll view is seeked and scrolled up
1514560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * to reclaim space. If scrolling is not possible or not enough, the popup
1515560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * window gets moved on top of the anchor.
1516560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * <p>
1517f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette     * The results of positioning are placed in {@code outParams}.
15185435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the view on which the popup window must be anchored
1520f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette     * @param outParams the layout parameters used to display the drop down
15219125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette     * @param xOffset absolute horizontal offset from the left of the anchor
15226acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette     * @param yOffset absolute vertical offset from the top of the anchor
1523560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette     * @param gravity horizontal gravity specifying popup alignment
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the popup is translated upwards to fit on screen
15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1526f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette    private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
1527f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette            int xOffset, int yOffset, int width, int height, int gravity) {
152862e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        final int anchorHeight = anchor.getHeight();
1529560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int anchorWidth = anchor.getWidth();
1530560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        if (mOverlapAnchor) {
1531f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette            yOffset -= anchorHeight;
1532560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        }
1533560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
15346acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette        // Initially, align to the bottom-left corner of the anchor plus offsets.
1535f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int[] drawingLocation = mTmpDrawingLocation;
1536f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        anchor.getLocationInWindow(drawingLocation);
1537f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        outParams.x = drawingLocation[0] + xOffset;
1538f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        outParams.y = drawingLocation[1] + anchorHeight + yOffset;
153954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
1540f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        final Rect displayFrame = new Rect();
1541f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        anchor.getWindowVisibleDisplayFrame(displayFrame);
15422665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr        if (width == MATCH_PARENT) {
1543f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr            width = displayFrame.right - displayFrame.left;
1544f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        }
15452665604edda9d5cfb6aa6b94a654982951ba20d3Robert Carr        if (height == MATCH_PARENT) {
1546f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr            height = displayFrame.bottom - displayFrame.top;
1547f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        }
1548f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr
1549cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        // Let the window manager know to align the top to y.
1550cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        outParams.gravity = Gravity.LEFT | Gravity.TOP;
1551cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        outParams.width = width;
1552cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        outParams.height = height;
1553cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr
15546acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette        // If we need to adjust for gravity RIGHT, align to the bottom-right
15556acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette        // corner of the anchor (still accounting for offsets).
1556560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette        final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
1557560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                & Gravity.HORIZONTAL_GRAVITY_MASK;
155854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        if (hgrav == Gravity.RIGHT) {
1559f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette            outParams.x -= width - anchorWidth;
156054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        }
1561560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
1562f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int[] screenLocation = mTmpScreenLocation;
1563f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        anchor.getLocationOnScreen(screenLocation);
156454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
15659125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        // First, attempt to fit the popup vertically without resizing.
15669125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final boolean fitsVertical = tryFitVertical(outParams, yOffset, height,
15679125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
15689125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                displayFrame.bottom, false);
15699125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
15709125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        // Next, attempt to fit the popup horizontally without resizing.
15719125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final boolean fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
15729125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
15739125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                displayFrame.right, false);
15749125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
15759125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        // If the popup still doesn't fit, attempt to scroll the parent.
15769125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (!fitsVertical || !fitsHorizontal) {
15779125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            final int scrollX = anchor.getScrollX();
15789125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            final int scrollY = anchor.getScrollY();
15799125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
15809125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                    scrollY + height + anchorHeight + yOffset);
15819125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
15829125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                // Reset for the new anchor position.
15839125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                anchor.getLocationInWindow(drawingLocation);
15849125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                outParams.x = drawingLocation[0] + xOffset;
15859125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                outParams.y = drawingLocation[1] + anchorHeight + yOffset;
15869125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
15879125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                // Preserve the gravity adjustment.
15889125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                if (hgrav == Gravity.RIGHT) {
15899125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                    outParams.x -= width - anchorWidth;
15909125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                }
1591b7c1b20c8a5a4d4378ae91b4a1f12a34100df452Adam Powell            }
15923e141685003939a9addce21ba2492ea3a8aebee6Romain Guy
15939125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // Try to fit the popup again and allowing resizing.
15949125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
15959125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                    screenLocation[1], displayFrame.top, displayFrame.bottom, mClipToScreen);
15969125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
15979125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                    screenLocation[0], displayFrame.left, displayFrame.right, mClipToScreen);
15989125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
159954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
16009125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        // Return whether the popup's top edge is above the anchor's top edge.
16019125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        return outParams.y < drawingLocation[1];
16029125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    }
1603560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
16049125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    private boolean tryFitVertical(@NonNull LayoutParams outParams, int yOffset, int height,
16059125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
16069125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int displayFrameBottom, boolean allowResize) {
160755f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        final int winOffsetY = screenLocationY - drawingLocationY;
160855f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        final int anchorTopInScreen = outParams.y + winOffsetY;
16099125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int spaceBelow = displayFrameBottom - anchorTopInScreen;
161055f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        if (anchorTopInScreen >= 0 && height <= spaceBelow) {
16119125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            return true;
16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1614b8320f7c58b46fea23e2827c82b46783b8c71b63Robert Carr        final int spaceAbove = anchorTopInScreen - anchorHeight - displayFrameTop;
16159125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (height <= spaceAbove) {
16169125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // Move everything up.
16179125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            if (mOverlapAnchor) {
16189125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                yOffset += anchorHeight;
161956c2d337e02a275397fc9d0460dca90977f199acAdam Powell            }
16209125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            outParams.y = drawingLocationY - height + yOffset;
16219125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16229125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            return true;
16239125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
1624560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
16259125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (positionInDisplayVertical(outParams, height, drawingLocationY, screenLocationY,
16269125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                displayFrameTop, displayFrameBottom, allowResize)) {
16279125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            return true;
16289125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
1629f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette
16309125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        return false;
16319125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    }
163256c2d337e02a275397fc9d0460dca90977f199acAdam Powell
16339125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    private boolean positionInDisplayVertical(@NonNull LayoutParams outParams, int height,
16349125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int drawingLocationY, int screenLocationY, int displayFrameTop, int displayFrameBottom,
16359125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            boolean canResize) {
16369125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        boolean fitsInDisplay = true;
16376acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette
16389125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int winOffsetY = screenLocationY - drawingLocationY;
16399125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        outParams.y += winOffsetY;
16409125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        outParams.height = height;
16419125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16429125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int bottom = outParams.y + height;
16439125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (bottom > displayFrameBottom) {
16449125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // The popup is too far down, move it back in.
16459125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            outParams.y -= bottom - displayFrameBottom;
16469125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
16476acf2f909b3f2a8f00775cfe3bd48cd0f44a577dAlan Viverette
16489125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (outParams.y < displayFrameTop) {
16499125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // The popup is too far up, move it back in and clip if
16509125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // it's still too large.
16519125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            outParams.y = displayFrameTop;
16529125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16539125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            final int displayFrameHeight = displayFrameBottom - displayFrameTop;
16549125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            if (canResize && height > displayFrameHeight) {
16559125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                outParams.height = displayFrameHeight;
16569125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            } else {
16579125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                fitsInDisplay = false;
16585f83a6017bacb513610df83a36b1f55953e65ad4Adam Powell            }
16599125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
16609125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16619125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        outParams.y -= winOffsetY;
1662f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette
16639125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        return fitsInDisplay;
16649125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    }
16659125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16669125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    private boolean tryFitHorizontal(@NonNull LayoutParams outParams, int xOffset, int width,
16679125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int anchorWidth, int drawingLocationX, int screenLocationX, int displayFrameLeft,
16689125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int displayFrameRight, boolean allowResize) {
166955f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        final int winOffsetX = screenLocationX - drawingLocationX;
167055f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        final int anchorLeftInScreen = outParams.x + winOffsetX;
16719125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int spaceRight = displayFrameRight - anchorLeftInScreen;
167255f0a99076477b77e017454e4356d908c43c2d22Alan Viverette        if (anchorLeftInScreen >= 0 && width <= spaceRight) {
16739125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            return true;
167456c2d337e02a275397fc9d0460dca90977f199acAdam Powell        }
167556c2d337e02a275397fc9d0460dca90977f199acAdam Powell
16769125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (positionInDisplayHorizontal(outParams, width, drawingLocationX, screenLocationX,
16779125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                displayFrameLeft, displayFrameRight, allowResize)) {
16789125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            return true;
16799125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
16809125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16819125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        return false;
16829125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    }
16839125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16849125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette    private boolean positionInDisplayHorizontal(@NonNull LayoutParams outParams, int width,
16859125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            int drawingLocationX, int screenLocationX, int displayFrameLeft, int displayFrameRight,
16869125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            boolean canResize) {
16879125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        boolean fitsInDisplay = true;
16889125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16899125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        // Use screen coordinates for comparison against display frame.
16909125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int winOffsetX = screenLocationX - drawingLocationX;
16919125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        outParams.x += winOffsetX;
16929125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16939125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        final int right = outParams.x + width;
16949125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (right > displayFrameRight) {
16959125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // The popup is too far right, move it back in.
16969125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            outParams.x -= right - displayFrameRight;
16979125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
16989125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
16999125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        if (outParams.x < displayFrameLeft) {
17009125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // The popup is too far left, move it back in and clip if it's
17019125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            // still too large.
17029125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            outParams.x = displayFrameLeft;
17039125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
17049125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            final int displayFrameWidth = displayFrameRight - displayFrameLeft;
17059125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            if (canResize && width > displayFrameWidth) {
17069125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                outParams.width = displayFrameWidth;
17079125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            } else {
17089125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette                fitsInDisplay = false;
17099125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette            }
17109125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        }
17119125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette
17129125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        outParams.x -= winOffsetX;
1713560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette
17149125fbacd85a4a0b8993886aacfe66091cd4f463Alan Viverette        return fitsInDisplay;
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17165435a30ae552391f14009c4459731ae149675b18Alan Viverette
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
17225435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1727b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(@NonNull View anchor) {
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return getMaxAvailableHeight(anchor, 0);
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the maximum height that is available for the popup to be
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * completely shown. It is recommended that this height be the maximum for
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the popup's height, otherwise it is possible that the popup will be
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clipped.
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor The view on which the popup window must be anchored.
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yOffset y offset from the view's bottom edge
17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The maximum available height for the popup to be completely
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         shown.
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1742b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(@NonNull View anchor, int yOffset) {
174398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau        return getMaxAvailableHeight(anchor, yOffset, false);
174498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    }
17455435a30ae552391f14009c4459731ae149675b18Alan Viverette
174698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau    /**
174798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * Returns the maximum height that is available for the popup to be
174898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * completely shown, optionally ignoring any bottom decorations such as
174998acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the input method. It is recommended that this height be the maximum for
175098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * the popup's height, otherwise it is possible that the popup will be
175198acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * clipped.
17525435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
175398acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param anchor The view on which the popup window must be anchored.
175498acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param yOffset y offset from the view's bottom edge
175598acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @param ignoreBottomDecorations if true, the height returned will be
175698acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        all the way to the bottom of the display, ignoring any
175798acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *        bottom decorations
175898acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     * @return The maximum available height for the popup to be completely
175998acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     *         shown.
176098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau     */
1761b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette    public int getMaxAvailableHeight(
1762b854d07a1a0fcd29c8f10255e616d387b9d436ccAlan Viverette            @NonNull View anchor, int yOffset, boolean ignoreBottomDecorations) {
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Rect displayFrame = new Rect();
17648175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        if (ignoreBottomDecorations) {
17658175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi            anchor.getWindowDisplayFrame(displayFrame);
17668175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        } else {
17678175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi            anchor.getWindowVisibleDisplayFrame(displayFrame);
17688175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        }
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1770f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int[] anchorPos = mTmpDrawingLocation;
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        anchor.getLocationOnScreen(anchorPos);
17725435a30ae552391f14009c4459731ae149675b18Alan Viverette
17738175846ed686077736c985f0ae4d236b7a4c647cJorim Jaggi        final int bottomEdge = displayFrame.bottom;
1774ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg
1775ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        final int distanceToBottom;
1776ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        if (mOverlapAnchor) {
1777ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            distanceToBottom = bottomEdge - anchorPos[1] - yOffset;
1778ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        } else {
1779ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg            distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
1780ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg        }
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // anchorPos[1] is distance from anchor to top of screen
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int returnedHeight = Math.max(distanceToBottom, distanceToTop);
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mBackground != null) {
17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBackground.getPadding(mTempRect);
17875435a30ae552391f14009c4459731ae149675b18Alan Viverette            returnedHeight -= mTempRect.top + mTempRect.bottom;
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17895435a30ae552391f14009c4459731ae149675b18Alan Viverette
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return returnedHeight;
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17925435a30ae552391f14009c4459731ae149675b18Alan Viverette
17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
17947878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * Disposes of the popup window. This method can be invoked only after
17957878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * {@link #showAsDropDown(android.view.View)} has been executed. Failing
17967878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette     * that, calling this method will have no effect.
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17985435a30ae552391f14009c4459731ae149675b18Alan Viverette     * @see #showAsDropDown(android.view.View)
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dismiss() {
18018fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (!isShowing() || mIsTransitioningToDismiss) {
1802e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            return;
1803e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        }
180406f938e8aa56cd89ab0bdb04c8b946392c428dd1Svetoslav Ganov
18058fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final PopupDecorView decorView = mDecorView;
18068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final View contentView = mContentView;
18078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
18088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewGroup contentHolder;
18098fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        final ViewParent contentParent = contentView.getParent();
18108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentParent instanceof ViewGroup) {
18118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = ((ViewGroup) contentParent);
18128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        } else {
18138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder = null;
18148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
18158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
18168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // Ensure any ongoing or pending transitions are canceled.
18178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        decorView.cancelTransitions();
18188fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
1819e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        mIsShowing = false;
18208fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = true;
1821b82d074038f4c8d86e1bd4f3fa4d3780bd4bcba5Craig Mautner
1822634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // This method may be called as part of window detachment, in which
1823634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // case the anchor view (and its root) will still return true from
1824634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // isAttachedToWindow() during execution of this method; however, we
1825634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // can expect the OnAttachStateChangeListener to have been called prior
1826634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        // to executing this method, so we can rely on that instead.
182795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final Transition exitTransition = mExitTransition;
182821d361806c9e2dce5bae5b30f44be5ad87f32c22Alan Viverette        if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
1829dbd299de2a07a2a0a490d4f37cf92870bf87d6c1Yohei Yukawa            // The decor view is non-interactive and non-IME-focusable during exit transitions.
183095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
183195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
183295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
1833dbd299de2a07a2a0a490d4f37cf92870bf87d6c1Yohei Yukawa            p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
183495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            mWindowManager.updateViewLayout(decorView, p);
183595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
1836634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // Once we start dismissing the decor view, all state (including
1837634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // the anchor root) needs to be moved to the decor view since we
1838634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // may open another popup while it's busy exiting.
1839634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
184091098574f90277128415e9593cce1e495cc51465Alan Viverette            final Rect epicenter = getTransitionEpicenter();
184195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            exitTransition.setEpicenterCallback(new EpicenterCallback() {
184295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                @Override
184395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                public Rect onGetEpicenter(Transition transition) {
184495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                    return epicenter;
184595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                }
184695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            });
1847634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            decorView.startExitTransition(exitTransition, anchorRoot,
1848634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    new TransitionListenerAdapter() {
1849634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        @Override
1850634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        public void onTransitionEnd(Transition transition) {
18517970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette                            dismissImmediate(decorView, contentHolder, contentView);
1852634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        }
1853634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    });
1854e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        } else {
18557970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette            dismissImmediate(decorView, contentHolder, contentView);
18567878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette        }
18577878edfa1dacf20c6120dbf18327905d6bf117d0Alan Viverette
185895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        // Clears the anchor view.
1859f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        detachFromAnchor();
18607970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette
18617970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette        if (mOnDismissListener != null) {
18627970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette            mOnDismissListener.onDismiss();
18637970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette        }
18645435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
18655435a30ae552391f14009c4459731ae149675b18Alan Viverette
186691098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
186791098574f90277128415e9593cce1e495cc51465Alan Viverette     * Returns the window-relative epicenter bounds to be used by enter and
186891098574f90277128415e9593cce1e495cc51465Alan Viverette     * exit transitions.
186991098574f90277128415e9593cce1e495cc51465Alan Viverette     * <p>
187091098574f90277128415e9593cce1e495cc51465Alan Viverette     * <strong>Note:</strong> This is distinct from the rect passed to
187191098574f90277128415e9593cce1e495cc51465Alan Viverette     * {@link #setEpicenterBounds(Rect)}, which is anchor-relative.
187291098574f90277128415e9593cce1e495cc51465Alan Viverette     *
187391098574f90277128415e9593cce1e495cc51465Alan Viverette     * @return the window-relative epicenter bounds to be used by enter and
187491098574f90277128415e9593cce1e495cc51465Alan Viverette     *         exit transitions
187591098574f90277128415e9593cce1e495cc51465Alan Viverette     */
187691098574f90277128415e9593cce1e495cc51465Alan Viverette    private Rect getTransitionEpicenter() {
187795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final View anchor = mAnchor != null ? mAnchor.get() : null;
187895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final View decor = mDecorView;
187995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        if (anchor == null || decor == null) {
188095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette            return null;
188195888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        }
188295888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
188395888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final int[] anchorLocation = anchor.getLocationOnScreen();
188495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final int[] popupLocation = mDecorView.getLocationOnScreen();
188595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
188695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        // Compute the position of the anchor relative to the popup.
188795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        final Rect bounds = new Rect(0, 0, anchor.getWidth(), anchor.getHeight());
188895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        bounds.offset(anchorLocation[0] - popupLocation[0], anchorLocation[1] - popupLocation[1]);
188991098574f90277128415e9593cce1e495cc51465Alan Viverette
189091098574f90277128415e9593cce1e495cc51465Alan Viverette        // Use anchor-relative epicenter, if specified.
189191098574f90277128415e9593cce1e495cc51465Alan Viverette        if (mEpicenterBounds != null) {
189291098574f90277128415e9593cce1e495cc51465Alan Viverette            final int offsetX = bounds.left;
189391098574f90277128415e9593cce1e495cc51465Alan Viverette            final int offsetY = bounds.top;
189491098574f90277128415e9593cce1e495cc51465Alan Viverette            bounds.set(mEpicenterBounds);
189591098574f90277128415e9593cce1e495cc51465Alan Viverette            bounds.offset(offsetX, offsetY);
189691098574f90277128415e9593cce1e495cc51465Alan Viverette        }
189791098574f90277128415e9593cce1e495cc51465Alan Viverette
189895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette        return bounds;
189995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette    }
190095888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette
19015435a30ae552391f14009c4459731ae149675b18Alan Viverette    /**
19025435a30ae552391f14009c4459731ae149675b18Alan Viverette     * Removes the popup from the window manager and tears down the supporting
19035435a30ae552391f14009c4459731ae149675b18Alan Viverette     * view hierarchy, if necessary.
19045435a30ae552391f14009c4459731ae149675b18Alan Viverette     */
19057970894a9c446a6c8260d28b5b5ec922cc3e7010Alan Viverette    private void dismissImmediate(View decorView, ViewGroup contentHolder, View contentView) {
19068fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // If this method gets called and the decor view doesn't have a parent,
19078fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // then it was either never added or was already removed. That should
19088fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // never happen, but it's worth checking to avoid potential crashes.
19098fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (decorView.getParent() != null) {
19108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mWindowManager.removeViewImmediate(decorView);
1911df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette        }
1912df4639a0135ea643b493067b3f7cd1e092346c78Alan Viverette
19138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        if (contentHolder != null) {
19148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            contentHolder.removeView(contentView);
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
19178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // This needs to stay until after all transitions have ended since we
19188fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        // need the reference to cancel transitions in preparePopup().
19198fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mDecorView = null;
1920697804e8de9f0a838a90c571baad19c5ed4d1647Alan Viverette        mBackgroundView = null;
19218fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        mIsTransitioningToDismiss = false;
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the listener to be called when the window is dismissed.
19265435a30ae552391f14009c4459731ae149675b18Alan Viverette     *
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param onDismissListener The listener.
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnDismissListener(OnDismissListener onDismissListener) {
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOnDismissListener = onDismissListener;
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19325435a30ae552391f14009c4459731ae149675b18Alan Viverette
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Updates the state of the popup window, if it is currently being displayed,
1935259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * from the currently set state.
1936259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1937259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * This includes:
1938259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <ul>
1939259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setClippingEnabled(boolean)}</li>
1940259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setFocusable(boolean)}</li>
1941259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setIgnoreCheekPress()}</li>
1942259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setInputMethodMode(int)}</li>
1943259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setTouchable(boolean)}</li>
1944259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *     <li>{@link #setAnimationStyle(int)}</li>
1945259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * </ul>
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update() {
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19515435a30ae552391f14009c4459731ae149675b18Alan Viverette
19525435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
19535435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
19545435a30ae552391f14009c4459731ae149675b18Alan Viverette
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = false;
19565435a30ae552391f14009c4459731ae149675b18Alan Viverette
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1968b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
1969489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        final int newGravity = computeGravity();
1970489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        if (newGravity != p.gravity) {
1971489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr            p.gravity = newGravity;
1972489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr            update = true;
1973489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        }
1974489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
1976b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
19775435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1980d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy
1981d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    /**
1982259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the dimension of the popup window.
1983259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1984259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
1985259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
1986d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     *
1987c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the new width in pixels, must be >= 0 or -1 to ignore
1988c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the new height in pixels, must be >= 0 or -1 to ignore
1989d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy     */
1990d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    public void update(int width, int height) {
19915435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
19925435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
1993d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy        update(p.x, p.y, width, height, false);
1994d6a463a9f23b3901bf729f2f27a6bb8f78b95248Romain Guy    }
19955435a30ae552391f14009c4459731ae149675b18Alan Viverette
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1997259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
1998259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
1999259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
2000259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
2001259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
2005c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the new width in pixels, must be >= 0 or -1 to ignore
2006c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the new height in pixels, must be >= 0 or -1 to ignore
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height) {
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        update(x, y, width, height, false);
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2013259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
2014259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
2015259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
2016259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
2017259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x the new x location
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y the new y location
2021c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the new width in pixels, must be >= 0 or -1 to ignore
2022c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the new height in pixels, must be >= 0 or -1 to ignore
2023259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * @param force {@code true} to reposition the window even if the specified
2024259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              position already seems to correspond to the LayoutParams,
2025259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     *              {@code false} to only reposition if needed
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(int x, int y, int width, int height, boolean force) {
2028259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (width >= 0) {
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastWidth = width;
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setWidth(width);
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2033259c2840691a79634ffd8f63291ec21c21819542Alan Viverette        if (height >= 0) {
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastHeight = height;
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setHeight(height);
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20425435a30ae552391f14009c4459731ae149675b18Alan Viverette        final WindowManager.LayoutParams p =
20435435a30ae552391f14009c4459731ae149675b18Alan Viverette                (WindowManager.LayoutParams) mDecorView.getLayoutParams();
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean update = force;
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
20489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width != -1 && p.width != finalWidth) {
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.width = mLastWidth = finalWidth;
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (height != -1 && p.height != finalHeight) {
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.height = mLastHeight = finalHeight;
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.x != x) {
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.x = x;
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p.y != y) {
20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.y = y;
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newAnim = computeAnimationResource();
20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newAnim != p.windowAnimations) {
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.windowAnimations = newAnim;
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int newFlags = computeFlags(p.flags);
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newFlags != p.flags) {
20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.flags = newFlags;
20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            update = true;
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
208098acd54fa6657e8131b3a2a957de7882a2f511abMike LeBeau
2081489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        final int newGravity = computeGravity();
2082489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        if (newGravity != p.gravity) {
2083489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr            p.gravity = newGravity;
2084489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr            update = true;
2085489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr        }
2086489c39d2db3be43e34c5ac55e09d8c17a5a04688Robert Carr
2087396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver        int newAccessibilityIdOfAnchor =
2088396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver                (mAnchor != null) ? mAnchor.get().getAccessibilityViewId() : -1;
2089396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver        if (newAccessibilityIdOfAnchor != p.accessibilityIdOfAnchor) {
2090396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver            p.accessibilityIdOfAnchor = newAccessibilityIdOfAnchor;
2091396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver            update = true;
2092396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver        }
2093396d549113bc633f719acc643c7dfc5f2a8fae4ePhil Weaver
20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (update) {
2095b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio            setLayoutDirectionFromAnchor();
20965435a30ae552391f14009c4459731ae149675b18Alan Viverette            mWindowManager.updateViewLayout(mDecorView, p);
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2101259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
2102259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
2103259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Calling this function also updates the window with the current popup
2104259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * state as described for {@link #update()}.
21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
2107c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the new width in pixels, must be >= 0 or -1 to ignore
2108c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the new height in pixels, must be >= 0 or -1 to ignore
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int width, int height) {
2111b91d6d06b824aab4076fb985304a602806429042Alan Viverette        update(anchor, false, 0, 0, width, height);
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2115259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Updates the position and the dimension of the popup window.
2116259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
2117259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * Width and height can be set to -1 to update location only. Calling this
2118259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * function also updates the window with the current popup state as
2119259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * described for {@link #update()}.
2120259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * <p>
2121259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * If the view later scrolls to move {@code anchor} to a different
2122259c2840691a79634ffd8f63291ec21c21819542Alan Viverette     * location, the popup will be moved correspondingly.
21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param anchor the popup's anchor view
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param xoff x offset from the view's left edge
21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param yoff y offset from the view's bottom edge
2127c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param width the new width in pixels, must be >= 0 or -1 to ignore
2128c129b58ad108b898ab829b6389ccf2b9196211a7Alan Viverette     * @param height the new height in pixels, must be >= 0 or -1 to ignore
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void update(View anchor, int xoff, int yoff, int width, int height) {
2131b91d6d06b824aab4076fb985304a602806429042Alan Viverette        update(anchor, true, xoff, yoff, width, height);
2132105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2133105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2134105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    private void update(View anchor, boolean updateLocation, int xoff, int yoff,
2135b91d6d06b824aab4076fb985304a602806429042Alan Viverette            int width, int height) {
2136105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isShowing() || mContentView == null) {
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
214175d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final WeakReference<View> oldAnchor = mAnchor;
2142f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int gravity = mAnchoredGravity;
2143f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette
214475d837954c3673647e3a899f03cd56c0892066e0Alan Viverette        final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
214581f08086b44a117097960195d2c9072e29644962Gilles Debunne        if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
2146f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette            attachToAnchor(anchor, xoff, yoff, gravity);
214781f08086b44a117097960195d2c9072e29644962Gilles Debunne        } else if (needsUpdate) {
214881f08086b44a117097960195d2c9072e29644962Gilles Debunne            // No need to register again if this is a DropDown, showAsDropDown already did.
214981f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorXoff = xoff;
215081f08086b44a117097960195d2c9072e29644962Gilles Debunne            mAnchorYoff = yoff;
21519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2153f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final LayoutParams p = (LayoutParams) mDecorView.getLayoutParams();
2154f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int oldGravity = p.gravity;
2155f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int oldWidth = p.width;
2156f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int oldHeight = p.height;
2157f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int oldX = p.x;
2158f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final int oldY = p.y;
2159f95b2d9aabc2e989bd1d665e728922b1c529589aAlan Viverette
2160b91d6d06b824aab4076fb985304a602806429042Alan Viverette        // If an explicit width/height has not specified, use the most recent
2161b91d6d06b824aab4076fb985304a602806429042Alan Viverette        // explicitly specified value (either from setWidth/Height or update).
2162f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        if (width < 0) {
2163b91d6d06b824aab4076fb985304a602806429042Alan Viverette            width = mWidth;
2164b91d6d06b824aab4076fb985304a602806429042Alan Viverette        }
2165f6e801da1a45b2458679e20f5e6061442a434e1bRobert Carr        if (height < 0) {
2166b91d6d06b824aab4076fb985304a602806429042Alan Viverette            height = mHeight;
21679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2168105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project
2169f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final boolean aboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
2170f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette                width, height, gravity);
2171f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        updateAboveAnchor(aboveAnchor);
2172b003e28c1d65d06fcb5690ff2955d007d8f7a626Fabrice Di Meglio
2173f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        final boolean paramsChanged = oldGravity != p.gravity || oldX != p.x || oldY != p.y
2174f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette                || oldWidth != p.width || oldHeight != p.height;
2175cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        // If width and mWidth were both < 0 then we have a MATCH_PARENT/WRAP_CONTENT case.
2176cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        // findDropDownPosition will have resolved this to absolute values,
2177cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        // but we don't want to update mWidth/mHeight to these absolute values.
2178cb8dcec66aa68e576bfd1520d1ad39a961f22c56Robert Carr        update(p.x, p.y, width < 0 ? width : p.width, height < 0 ? height : p.height, paramsChanged);
21799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
21829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Listener that is called when this popup window is dismissed.
21839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
21849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public interface OnDismissListener {
21859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
21869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Called when this popup window is dismissed.
21879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
21889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onDismiss();
21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2191f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette    private void detachFromAnchor() {
2192634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchor = mAnchor != null ? mAnchor.get() : null;
21939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (anchor != null) {
2194e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette            final ViewTreeObserver vto = anchor.getViewTreeObserver();
21959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.removeOnScrollChangedListener(mOnScrollChangedListener);
21969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2197e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
2198634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
2199634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        if (anchorRoot != null) {
2200634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2201634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        }
2202634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
22039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchor = null;
2204634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchorRoot = null;
2205634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mIsAnchorRootAttached = false;
22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2208f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette    private void attachToAnchor(View anchor, int xoff, int yoff, int gravity) {
2209f50df4362a8ec8c79ff1b9508a57be51f293897aAlan Viverette        detachFromAnchor();
2210e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette
2211e025ed2f26858dae5f40a94a2e1ac0db808a6950Alan Viverette        final ViewTreeObserver vto = anchor.getViewTreeObserver();
22129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (vto != null) {
22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            vto.addOnScrollChangedListener(mOnScrollChangedListener);
22149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2216634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        final View anchorRoot = anchor.getRootView();
2217634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2218634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2219634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchor = new WeakReference<>(anchor);
2220634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mAnchorRoot = new WeakReference<>(anchorRoot);
2221634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        mIsAnchorRootAttached = anchorRoot.isAttachedToWindow();
2222634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
22239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorXoff = xoff;
22249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAnchorYoff = yoff;
222554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mAnchoredGravity = gravity;
22269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22285435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupDecorView extends FrameLayout {
22298fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private TransitionListenerAdapter mPendingExitListener;
22308fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22315435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupDecorView(Context context) {
22325435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
22335435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
22349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
22369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchKeyEvent(KeyEvent event) {
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
22384ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                if (getKeyDispatcherState() == null) {
22394ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                    return super.dispatchKeyEvent(event);
22404ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson                }
22414ae02b37bb0ee0a9a626108299b6a2e9ac028ca2Per Andersson
22425435a30ae552391f14009c4459731ae149675b18Alan Viverette                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
22435435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
2244b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null) {
2245b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        state.startTracking(event, this);
2246b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
22478d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    return true;
2248b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                } else if (event.getAction() == KeyEvent.ACTION_UP) {
22495435a30ae552391f14009c4459731ae149675b18Alan Viverette                    final KeyEvent.DispatcherState state = getKeyDispatcherState();
2250b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    if (state != null && state.isTracking(event) && !event.isCanceled()) {
2251b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        dismiss();
2252b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                        return true;
2253b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    }
22548d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                }
22558d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                return super.dispatchKeyEvent(event);
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
22579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.dispatchKeyEvent(event);
22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean dispatchTouchEvent(MotionEvent ev) {
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mTouchInterceptor != null && mTouchInterceptor.onTouch(this, ev)) {
22649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
22659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.dispatchTouchEvent(ev);
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean onTouchEvent(MotionEvent event) {
22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int x = (int) event.getX();
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int y = (int) event.getY();
22735435a30ae552391f14009c4459731ae149675b18Alan Viverette
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if ((event.getAction() == MotionEvent.ACTION_DOWN)
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
22779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dismiss();
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return super.onTouchEvent(event);
22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22858fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22868fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
22878fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Requests that an enter transition run after the next layout pass.
22888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
22898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void requestEnterTransition(Transition transition) {
22908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final ViewTreeObserver observer = getViewTreeObserver();
22918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (observer != null && transition != null) {
22928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final Transition enterTransition = transition.clone();
22938fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
22948fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                // Postpone the enter transition after the first layout pass.
22958fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
22968fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    @Override
22978fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    public void onGlobalLayout() {
22988fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        final ViewTreeObserver observer = getViewTreeObserver();
22998fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        if (observer != null) {
23008fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                            observer.removeOnGlobalLayoutListener(this);
23018fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        }
23028fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
230391098574f90277128415e9593cce1e495cc51465Alan Viverette                        final Rect epicenter = getTransitionEpicenter();
230495888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                        enterTransition.setEpicenterCallback(new EpicenterCallback() {
230595888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            @Override
230695888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            public Rect onGetEpicenter(Transition transition) {
230795888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                                return epicenter;
230895888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                            }
230995888c07e978f0d6af62ef96124acd228ac2ab13Alan Viverette                        });
23108fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                        startEnterTransition(enterTransition);
23118fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    }
23128fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                });
23138fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23148fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
23158fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23168fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
23178fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts the pending enter transition, if one is set.
23188fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
23198fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        private void startEnterTransition(Transition enterTransition) {
23208fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
23218fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
23228fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
23238fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                enterTransition.addTarget(child);
23248fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
23258fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23268fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23278fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, enterTransition);
23288fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23298fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
23308fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
23318fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.VISIBLE);
23328fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23338fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
23348fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23358fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
23368fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Starts an exit transition immediately.
23378fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <p>
23388fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * <strong>Note:</strong> The transition listener is guaranteed to have
23398fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * its {@code onTransitionEnd} method called even if the transition
23408fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * never starts; however, it may be called with a {@code null} argument.
23418fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
2342634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        public void startExitTransition(Transition transition, final View anchorRoot,
2343634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                final TransitionListener listener) {
23448fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (transition == null) {
23458fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                return;
23468fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23478fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
2348634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // The anchor view's window may go away while we're executing our
2349634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // transition, in which case we need to end the transition
2350634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            // immediately and execute the listener to remove the popup.
2351634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette            anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
2352634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
23538fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // The exit listener MUST be called for cleanup, even if the
23548fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            // transition never starts or ends. Stash it for later.
23558fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            mPendingExitListener = new TransitionListenerAdapter() {
23568fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                @Override
23578fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                public void onTransitionEnd(Transition transition) {
2358634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
23598fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    listener.onTransitionEnd(transition);
23608fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23618fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    // The listener was called. Our job here is done.
23628fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                    mPendingExitListener = null;
23638fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                }
23648fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            };
23658fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23668fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final Transition exitTransition = transition.clone();
23678fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            exitTransition.addListener(mPendingExitListener);
23688fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23698fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            final int count = getChildCount();
23708fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
23718fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
23728fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                exitTransition.addTarget(child);
23738fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23748fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23758fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.beginDelayedTransition(this, exitTransition);
23768fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23778fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            for (int i = 0; i < count; i++) {
23788fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                final View child = getChildAt(i);
23798fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                child.setVisibility(View.INVISIBLE);
23808fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23818fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
23828fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23838fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        /**
23848fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         * Cancels all pending or current transitions.
23858fd949e680c15d397084430d4907c16cedfacddaAlan Viverette         */
23868fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        public void cancelTransitions() {
23878fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            TransitionManager.endTransitions(this);
23888fd949e680c15d397084430d4907c16cedfacddaAlan Viverette
23898fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            if (mPendingExitListener != null) {
23908fd949e680c15d397084430d4907c16cedfacddaAlan Viverette                mPendingExitListener.onTransitionEnd(null);
23918fd949e680c15d397084430d4907c16cedfacddaAlan Viverette            }
23928fd949e680c15d397084430d4907c16cedfacddaAlan Viverette        }
2393634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2394634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette        private final OnAttachStateChangeListener mOnAnchorRootDetachedListener =
2395634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                new OnAttachStateChangeListener() {
2396634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    @Override
2397634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    public void onViewAttachedToWindow(View v) {}
2398634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2399634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    @Override
2400634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    public void onViewDetachedFromWindow(View v) {
2401634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        v.removeOnAttachStateChangeListener(this);
2402634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette
2403634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                        TransitionManager.endTransitions(PopupDecorView.this);
2404634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                    }
2405634a808226cc5d00bd6897bdc881cafe064e37acAlan Viverette                };
24065435a30ae552391f14009c4459731ae149675b18Alan Viverette    }
24075435a30ae552391f14009c4459731ae149675b18Alan Viverette
24085435a30ae552391f14009c4459731ae149675b18Alan Viverette    private class PopupBackgroundView extends FrameLayout {
24095435a30ae552391f14009c4459731ae149675b18Alan Viverette        public PopupBackgroundView(Context context) {
24105435a30ae552391f14009c4459731ae149675b18Alan Viverette            super(context);
24115435a30ae552391f14009c4459731ae149675b18Alan Viverette        }
241275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
241375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        @Override
24145435a30ae552391f14009c4459731ae149675b18Alan Viverette        protected int[] onCreateDrawableState(int extraSpace) {
24155435a30ae552391f14009c4459731ae149675b18Alan Viverette            if (mAboveAnchor) {
24165435a30ae552391f14009c4459731ae149675b18Alan Viverette                final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
24175435a30ae552391f14009c4459731ae149675b18Alan Viverette                View.mergeDrawableStates(drawableState, ABOVE_ANCHOR_STATE_SET);
24185435a30ae552391f14009c4459731ae149675b18Alan Viverette                return drawableState;
241975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            } else {
24205435a30ae552391f14009c4459731ae149675b18Alan Viverette                return super.onCreateDrawableState(extraSpace);
242175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
242275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
24239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2425