ListPopupWindow.java revision 76ecafcac7f7810de047f87931d58c04a8a86dc1
13565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/*
249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project
33565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
43565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Licensed under the Apache License, Version 2.0 (the "License");
53565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * you may not use this file except in compliance with the License.
63565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * You may obtain a copy of the License at
73565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
83565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *      http://www.apache.org/licenses/LICENSE-2.0
93565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Unless required by applicable law or agreed to in writing, software
113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * distributed under the License is distributed on an "AS IS" BASIS,
123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * See the License for the specific language governing permissions and
143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * limitations under the License.
153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */
163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.widget;
183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.content.Context;
20ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport android.content.res.TypedArray;
213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.database.DataSetObserver;
223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.Rect;
233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.drawable.Drawable;
2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.os.Build;
253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.os.Handler;
266142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.AttrRes;
276142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.NonNull;
286142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.Nullable;
296142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.StyleRes;
306142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v4.os.BuildCompat;
3118864e53490e04739f1063a7ee113549874f87b0Chris Banesimport android.support.v4.view.ViewCompat;
3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.widget.PopupWindowCompat;
33da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
346142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v7.view.menu.ShowableListMenu;
353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.AttributeSet;
363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.Log;
3749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Gravity;
383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.KeyEvent;
393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.MotionEvent;
403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View;
413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.MeasureSpec;
423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.OnTouchListener;
433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewGroup;
443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewParent;
4518864e53490e04739f1063a7ee113549874f87b0Chris Banesimport android.view.WindowManager;
4649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.AbsListView;
4749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.AdapterView;
486142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.widget.AdapterView.OnItemSelectedListener;
4949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.LinearLayout;
5049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.ListAdapter;
5149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.ListView;
5249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.PopupWindow;
533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
54ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport java.lang.reflect.Method;
553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/**
5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Static library support version of the framework's {@link android.widget.ListPopupWindow}.
5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Used to write apps that run on platforms prior to Android L. When running
5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * on Android L or above, this implementation is still used; it does not try
6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to switch to the framework's implementation. See the framework SDK
6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * documentation for a class overview.
623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see android.widget.ListPopupWindow
643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */
656142a54baae3289f734947c6b5375b12eb0fb722Chris Banespublic class ListPopupWindow implements ShowableListMenu {
663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final String TAG = "ListPopupWindow";
673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final boolean DEBUG = false;
683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
7049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * This value controls the length of time that the user
7149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * must leave a pointer down without scrolling to expand
7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the autocomplete dropdown list to cover the IME.
733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final int EXPAND_LIST_TIMEOUT = 250;
753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
76ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    private static Method sClipToWindowEnabledMethod;
777ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes    private static Method sGetMaxAvailableHeightMethod;
786142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    private static Method sSetEpicenterBoundsMethod;
79ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
80ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    static {
81ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        try {
82ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            sClipToWindowEnabledMethod = PopupWindow.class.getDeclaredMethod(
83ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                    "setClipToScreenEnabled", boolean.class);
84ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        } catch (NoSuchMethodException e) {
85ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            Log.i(TAG, "Could not find method setClipToScreenEnabled() on PopupWindow. Oh well.");
86ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
877ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        try {
887ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes            sGetMaxAvailableHeightMethod = PopupWindow.class.getDeclaredMethod(
897ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                    "getMaxAvailableHeight", View.class, int.class, boolean.class);
907ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        } catch (NoSuchMethodException e) {
917ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes            Log.i(TAG, "Could not find method getMaxAvailableHeight(View, int, boolean)"
927ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                    + " on PopupWindow. Oh well.");
937ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        }
946142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        try {
956142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            sSetEpicenterBoundsMethod = PopupWindow.class.getDeclaredMethod(
966142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                    "setEpicenterBounds", Rect.class);
976142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        } catch (NoSuchMethodException e) {
986142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            Log.i(TAG, "Could not find method setEpicenterBounds(Rect) on PopupWindow. Oh well.");
996142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        }
100ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    }
101ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
1023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Context mContext;
1033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private ListAdapter mAdapter;
1043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private DropDownListView mDropDownList;
1053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
1073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
1083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownHorizontalOffset;
1093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownVerticalOffset;
11018864e53490e04739f1063a7ee113549874f87b0Chris Banes    private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
1113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mDropDownVerticalOffsetSet;
1126142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    private boolean mIsAnimatedFromAnchor = true;
1133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private int mDropDownGravity = Gravity.NO_GRAVITY;
11549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mDropDownAlwaysVisible = false;
1173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mForceIgnoreOutsideTouch = false;
1183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    int mListItemExpandMaximum = Integer.MAX_VALUE;
1193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private View mPromptView;
1213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mPromptPosition = POSITION_PROMPT_ABOVE;
1223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private DataSetObserver mObserver;
1243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private View mDropDownAnchorView;
1263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Drawable mDropDownListHighlight;
1283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private AdapterView.OnItemClickListener mItemClickListener;
1306142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    private OnItemSelectedListener mItemSelectedListener;
1313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable();
1333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor();
1343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final PopupScrollListener mScrollListener = new PopupScrollListener();
1353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final ListSelectorHider mHideSelector = new ListSelectorHider();
1363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Runnable mShowDropDownRunnable;
1373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13818864e53490e04739f1063a7ee113549874f87b0Chris Banes    private final Handler mHandler;
1393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1406142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    private final Rect mTempRect = new Rect();
1416142a54baae3289f734947c6b5375b12eb0fb722Chris Banes
1426142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    /**
1436142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * Optional anchor-relative bounds to be used as the transition epicenter.
1446142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * When {@code null}, the anchor bounds are used as the epicenter.
1456142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     */
1466142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    private Rect mEpicenterBounds;
1473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mModal;
1493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    PopupWindow mPopup;
1513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
1533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * The provided prompt view should appear above list content.
1543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptPosition(int)
1563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getPromptPosition()
1573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptView(View)
1583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int POSITION_PROMPT_ABOVE = 0;
1603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
1623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * The provided prompt view should appear below list content.
1633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptPosition(int)
1653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getPromptPosition()
1663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptView(View)
1673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int POSITION_PROMPT_BELOW = 1;
1693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
17149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Alias for {@link ViewGroup.LayoutParams#MATCH_PARENT}.
17249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * If used to specify a popup width, the popup will match the width of the anchor view.
17349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * If used to specify a popup height, the popup will fill available space.
1743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
17549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT;
1763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
17849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
17949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * If used to specify a popup width, the popup will use the width of its content.
1803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
1823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
18449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
18549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * input method should be based on the focusability of the popup.  That is
18649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * if it is focusable than it needs to work with the input method, else
18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * it doesn't.
1883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE;
1903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * work with an input method, regardless of whether it is focusable.  This
19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * means that it will always be displayed so that the user can also operate
19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the input method while it is shown.
1963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED;
1983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * work with an input method, regardless of whether it is focusable.  This
20249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * means that it will always be displayed to use as much space on the
20349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * screen as needed, regardless of whether this covers the input method.
2043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_NOT_NEEDED = PopupWindow.INPUT_METHOD_NOT_NEEDED;
2063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
20849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Create a new, empty popup window capable of displaying items from a ListAdapter.
20949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
2103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param context Context used for contained views.
2123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public ListPopupWindow(@NonNull Context context) {
214ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns        this(context, null, R.attr.listPopupWindowStyle);
2153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Create a new, empty popup window capable of displaying items from a ListAdapter.
21949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
2203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param context Context used for contained views.
22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param attrs   Attributes from inflating parent views used to style the popup.
2233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2246142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs) {
225ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns        this(context, attrs, R.attr.listPopupWindowStyle);
2263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Create a new, empty popup window capable of displaying items from a ListAdapter.
23049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
2313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
23249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param context Context used for contained views.
23349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param attrs Attributes from inflating parent views used to style the popup.
2343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param defStyleAttr Default style attribute to use for popup content.
2353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2366142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
2376142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            @AttrRes int defStyleAttr) {
238a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette        this(context, attrs, defStyleAttr, 0);
239a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette    }
240a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette
241a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette    /**
242a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * Create a new, empty popup window capable of displaying items from a ListAdapter.
243a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
244a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     *
245a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * @param context Context used for contained views.
246a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * @param attrs Attributes from inflating parent views used to style the popup.
247a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * @param defStyleAttr Style attribute to read for default styling of popup content.
248a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     * @param defStyleRes Style resource ID to use for default styling of popup content.
249a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette     */
2506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
2516142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
2523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mContext = context;
25318864e53490e04739f1063a7ee113549874f87b0Chris Banes        mHandler = new Handler(context.getMainLooper());
254ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
255ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPopupWindow,
256a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette                defStyleAttr, defStyleRes);
257ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        mDropDownHorizontalOffset = a.getDimensionPixelOffset(
258ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                R.styleable.ListPopupWindow_android_dropDownHorizontalOffset, 0);
259ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        mDropDownVerticalOffset = a.getDimensionPixelOffset(
260ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                R.styleable.ListPopupWindow_android_dropDownVerticalOffset, 0);
261ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        if (mDropDownVerticalOffset != 0) {
262ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            mDropDownVerticalOffsetSet = true;
263ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
264ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        a.recycle();
265ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
2665ec2faa01bc6790bc015e0d5748dc0482ae8c0f2Chris Banes        mPopup = new AppCompatPopupWindow(context, attrs, defStyleAttr);
2673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
268ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns    }
2693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
27149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the adapter that provides the data and the views to represent the data
27249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * in this popup window.
2733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param adapter The adapter to use to create this window's content.
2753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2766142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setAdapter(@Nullable ListAdapter adapter) {
2773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mObserver == null) {
2783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mObserver = new PopupDataSetObserver();
2793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else if (mAdapter != null) {
2803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mAdapter.unregisterDataSetObserver(mObserver);
2813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mAdapter = adapter;
2833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mAdapter != null) {
2843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            adapter.registerDataSetObserver(mObserver);
2853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mDropDownList != null) {
2883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setAdapter(mAdapter);
2893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
29349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Set where the optional prompt view should appear. The default is
29449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #POSITION_PROMPT_ABOVE}.
2953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position A position constant declaring where the prompt should be displayed.
29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
2983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_ABOVE
2993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_BELOW
3003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setPromptPosition(int position) {
3023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPromptPosition = position;
3033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Where the optional prompt view should appear.
30749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
3083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_ABOVE
3093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_BELOW
3103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getPromptPosition() {
3123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPromptPosition;
3133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set whether this window should be modal when shown.
3173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
31849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>If a popup window is modal, it will receive all touch and key input.
31949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * If the user touches outside the popup window's content area the popup window
32049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * will be dismissed.
3213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param modal {@code true} if the popup window should be modal, {@code false} otherwise.
3233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setModal(boolean modal) {
325a2c72b87007d10202c25e78e904938f770c6337dChris Banes        mModal = modal;
3263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setFocusable(modal);
3273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns whether the popup window will be modal when shown.
3313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return {@code true} if the popup window will be modal, {@code false} otherwise.
3333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isModal() {
3353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mModal;
3363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
34049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
34149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * ignore outside touch even when the drop down is not set to always visible.
3423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Used only by AutoCompleteTextView to handle some internal special cases.
3443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
3463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
3473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets whether the drop-down should remain visible under certain conditions.
3513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
35249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless
35349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * of the size or content of the list.  {@link #getBackground()} will fill any space
35449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * that is not used by the list.
3553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
35749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
3583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Only used by AutoCompleteTextView under special conditions.
3593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
3613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownAlwaysVisible = dropDownAlwaysVisible;
3623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Whether the drop-down is visible under special conditions.
36649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
3673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Only used by AutoCompleteTextView under special conditions.
3683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isDropDownAlwaysVisible() {
3703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownAlwaysVisible;
3713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets the operating mode for the soft input area.
3753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
37649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param mode The desired mode, see
37749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
37849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *        for the full list
37949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
3803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see android.view.WindowManager.LayoutParams#softInputMode
3813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getSoftInputMode()
3823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setSoftInputMode(int mode) {
3843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setSoftInputMode(mode);
3853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns the current value in {@link #setSoftInputMode(int)}.
3893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setSoftInputMode(int)
3913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see android.view.WindowManager.LayoutParams#softInputMode
3923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getSoftInputMode() {
3943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getSoftInputMode();
3953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a drawable to use as the list item selector.
3993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param selector List selector drawable to use in the popup.
4013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setListSelector(Drawable selector) {
4033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownListHighlight = selector;
4043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The background drawable for the popup window.
4083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4096142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @Nullable Drawable getBackground() {
4103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getBackground();
4113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a drawable to be the background for the popup window.
4153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param d A drawable to set as the background.
4173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4186142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setBackgroundDrawable(@Nullable Drawable d) {
4193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setBackgroundDrawable(d);
4203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set an animation style to use when the popup window is shown or dismissed.
4243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param animationStyle Animation style to use.
4263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4276142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setAnimationStyle(@StyleRes int animationStyle) {
4283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setAnimationStyle(animationStyle);
4293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4326142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * Returns the animation style that will be used when the popup window is
4336142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * shown or dismissed.
4343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Animation style that will be used.
4363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4376142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @StyleRes int getAnimationStyle() {
4383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getAnimationStyle();
4393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns the view that will be used to anchor this popup.
4433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The popup's anchor view
4453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4466142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @Nullable View getAnchorView() {
4473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownAnchorView;
4483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4516142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * Sets the popup's anchor view. This popup will always be positioned relative to
4526142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * the anchor view when shown.
4533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param anchor The view to use as an anchor.
4553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4566142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setAnchorView(@Nullable View anchor) {
4573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownAnchorView = anchor;
4583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The horizontal offset of the popup from its anchor in pixels.
4623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getHorizontalOffset() {
4643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownHorizontalOffset;
4653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set the horizontal offset of this popup from its anchor view in pixels.
4693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param offset The horizontal offset of the popup from its anchor.
4713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setHorizontalOffset(int offset) {
4733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownHorizontalOffset = offset;
4743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The vertical offset of the popup from its anchor in pixels.
4783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getVerticalOffset() {
4803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!mDropDownVerticalOffsetSet) {
4813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return 0;
4823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
4833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownVerticalOffset;
4843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set the vertical offset of this popup from its anchor view in pixels.
4883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param offset The vertical offset of the popup from its anchor.
4903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setVerticalOffset(int offset) {
4923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownVerticalOffset = offset;
4933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownVerticalOffsetSet = true;
4943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4976142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * Specifies the anchor-relative bounds of the popup's transition
4986142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * epicenter.
4996142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     *
5006142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * @param bounds anchor-relative bounds
5016142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * @hide
5026142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     */
5036142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setEpicenterBounds(Rect bounds) {
5046142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        mEpicenterBounds = bounds;
5056142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    }
5066142a54baae3289f734947c6b5375b12eb0fb722Chris Banes
5076142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    /**
50849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Set the gravity of the dropdown list. This is commonly used to
50949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * set gravity to START or END for alignment with the anchor.
51049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
51149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param gravity Gravity value to use
51249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
51349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public void setDropDownGravity(int gravity) {
51449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        mDropDownGravity = gravity;
51549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
51649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
51749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
5183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The width of the popup window in pixels.
5193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getWidth() {
5213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownWidth;
5223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
52549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the width of the popup window in pixels. Can also be {@link #MATCH_PARENT}
52649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * or {@link #WRAP_CONTENT}.
5273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
5283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param width Width of the popup window.
5293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setWidth(int width) {
5313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownWidth = width;
5323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
53549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the width of the popup window by the size of its content. The final width may be
53649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * larger to accommodate styled window dressing.
5373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
5383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param width Desired width of content in pixels.
5393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setContentWidth(int width) {
5413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        Drawable popupBackground = mPopup.getBackground();
5423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (popupBackground != null) {
5433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            popupBackground.getPadding(mTempRect);
5443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownWidth = mTempRect.left + mTempRect.right + width;
5453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
5463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            setWidth(width);
5473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
5483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
5513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The height of the popup window in pixels.
5523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getHeight() {
5543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownHeight;
5553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
55849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}.
5593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
5603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param height Height of the popup window.
5613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setHeight(int height) {
5633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownHeight = height;
5643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
56718864e53490e04739f1063a7ee113549874f87b0Chris Banes     * Set the layout type for this popup window.
56818864e53490e04739f1063a7ee113549874f87b0Chris Banes     * <p>
56918864e53490e04739f1063a7ee113549874f87b0Chris Banes     * See {@link WindowManager.LayoutParams#type} for possible values.
57018864e53490e04739f1063a7ee113549874f87b0Chris Banes     *
57118864e53490e04739f1063a7ee113549874f87b0Chris Banes     * @param layoutType Layout type for this window.
57218864e53490e04739f1063a7ee113549874f87b0Chris Banes     *
57318864e53490e04739f1063a7ee113549874f87b0Chris Banes     * @see WindowManager.LayoutParams#type
57418864e53490e04739f1063a7ee113549874f87b0Chris Banes     */
57518864e53490e04739f1063a7ee113549874f87b0Chris Banes    public void setWindowLayoutType(int layoutType) {
57618864e53490e04739f1063a7ee113549874f87b0Chris Banes        mDropDownWindowLayoutType = layoutType;
57718864e53490e04739f1063a7ee113549874f87b0Chris Banes    }
57818864e53490e04739f1063a7ee113549874f87b0Chris Banes
57918864e53490e04739f1063a7ee113549874f87b0Chris Banes    /**
5803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a listener to receive events when a list item is clicked.
5813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
5823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param clickListener Listener to register
58349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
5843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
5853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5866142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) {
5873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mItemClickListener = clickListener;
5883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
5913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a listener to receive events when a list item is selected.
5923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
5933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param selectedListener Listener to register.
59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
5956142a54baae3289f734947c6b5375b12eb0fb722Chris Banes     * @see ListView#setOnItemSelectedListener(OnItemSelectedListener)
5963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5976142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) {
5983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mItemSelectedListener = selectedListener;
5993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set a view to act as a user prompt for this popup window. Where the prompt view will appear
6033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * is controlled by {@link #setPromptPosition(int)}.
6043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param prompt View to use as an informational prompt.
6063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6076142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setPromptView(@Nullable View prompt) {
6083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        boolean showing = isShowing();
6093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (showing) {
6103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            removePromptView();
6113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
6123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPromptView = prompt;
6133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (showing) {
6143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            show();
6153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
6163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Post a {@link #show()} call to the UI thread.
6203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void postShow() {
6223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mHandler.post(mShowDropDownRunnable);
6233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
62649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Show the popup list. If the list is already showing, this method
62749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * will recalculate the popup's size and position.
6283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6296142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @Override
6303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void show() {
6313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int height = buildDropDown();
6323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6336142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        final boolean noInputMethod = isInputMethodNotNeeded();
63418864e53490e04739f1063a7ee113549874f87b0Chris Banes        PopupWindowCompat.setWindowLayoutType(mPopup, mDropDownWindowLayoutType);
6353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mPopup.isShowing()) {
63718864e53490e04739f1063a7ee113549874f87b0Chris Banes            final int widthSpec;
63849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
6393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // The call to PopupWindow's update method below can accept -1 for any
6403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // value you do not want to update.
6413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = -1;
6423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
6433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = getAnchorView().getWidth();
6443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
6453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = mDropDownWidth;
6463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
64818864e53490e04739f1063a7ee113549874f87b0Chris Banes            final int heightSpec;
64949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
6503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // The call to PopupWindow's update method below can accept -1 for any
6513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // value you do not want to update.
65249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT;
6533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (noInputMethod) {
65418864e53490e04739f1063a7ee113549874f87b0Chris Banes                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
65518864e53490e04739f1063a7ee113549874f87b0Chris Banes                            ViewGroup.LayoutParams.MATCH_PARENT : 0);
65618864e53490e04739f1063a7ee113549874f87b0Chris Banes                    mPopup.setHeight(0);
6573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
65818864e53490e04739f1063a7ee113549874f87b0Chris Banes                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
65918864e53490e04739f1063a7ee113549874f87b0Chris Banes                                    ViewGroup.LayoutParams.MATCH_PARENT : 0);
66018864e53490e04739f1063a7ee113549874f87b0Chris Banes                    mPopup.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
6613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
6623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
6633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = height;
6643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
6653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = mDropDownHeight;
6663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
6693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
67118864e53490e04739f1063a7ee113549874f87b0Chris Banes                            mDropDownVerticalOffset, (widthSpec < 0)? -1 : widthSpec,
67218864e53490e04739f1063a7ee113549874f87b0Chris Banes                            (heightSpec < 0)? -1 : heightSpec);
6733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
67418864e53490e04739f1063a7ee113549874f87b0Chris Banes            final int widthSpec;
67549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
67649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                widthSpec = ViewGroup.LayoutParams.MATCH_PARENT;
6773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
6783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
67918864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthSpec = getAnchorView().getWidth();
6803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
68118864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthSpec = mDropDownWidth;
6823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
6833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
68518864e53490e04739f1063a7ee113549874f87b0Chris Banes            final int heightSpec;
68649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
68749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                heightSpec = ViewGroup.LayoutParams.MATCH_PARENT;
6883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
6893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
69018864e53490e04739f1063a7ee113549874f87b0Chris Banes                    heightSpec = height;
6913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
69218864e53490e04739f1063a7ee113549874f87b0Chris Banes                    heightSpec = mDropDownHeight;
6933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
6943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
69618864e53490e04739f1063a7ee113549874f87b0Chris Banes            mPopup.setWidth(widthSpec);
69718864e53490e04739f1063a7ee113549874f87b0Chris Banes            mPopup.setHeight(heightSpec);
698ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            setPopupClipToScreenEnabled(true);
6993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // use outside touchable to dismiss drop down when touching outside of it, so
7013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // only set this if the dropdown is not always visible
7023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
7033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setTouchInterceptor(mTouchInterceptor);
7046142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            if (sSetEpicenterBoundsMethod != null) {
7056142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                try {
7066142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                    sSetEpicenterBoundsMethod.invoke(mPopup, mEpicenterBounds);
7076142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                } catch (Exception e) {
7086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                    Log.e(TAG, "Could not invoke setEpicenterBounds on PopupWindow", e);
7096142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                }
7106142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            }
71149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            PopupWindowCompat.showAsDropDown(mPopup, getAnchorView(), mDropDownHorizontalOffset,
71249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    mDropDownVerticalOffset, mDropDownGravity);
7133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setSelection(ListView.INVALID_POSITION);
7143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mModal || mDropDownList.isInTouchMode()) {
7163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                clearListSelection();
7173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
7183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mModal) {
7193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.post(mHideSelector);
7203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
7213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
7253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Dismiss the popup window.
7263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7276142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @Override
7283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void dismiss() {
7293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.dismiss();
7303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        removePromptView();
7313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setContentView(null);
7323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownList = null;
7333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mHandler.removeCallbacks(mResizePopupRunnable);
7343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
7373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set a listener to receive a callback when the popup is dismissed.
7383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param listener Listener that will be notified when the popup is dismissed.
7403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7416142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public void setOnDismissListener(@Nullable PopupWindow.OnDismissListener listener) {
7423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setOnDismissListener(listener);
7433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private void removePromptView() {
7463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mPromptView != null) {
7473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final ViewParent parent = mPromptView.getParent();
7483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (parent instanceof ViewGroup) {
7493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ViewGroup group = (ViewGroup) parent;
7503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                group.removeView(mPromptView);
7513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
7523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
75649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Control how the popup operates with an input method: one of
75749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
75849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * or {@link #INPUT_METHOD_NOT_NEEDED}.
7593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
76049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>If the popup is showing, calling this method will take effect only
76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the next time the popup is shown or through a manual call to the {@link #show()}
76249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * method.</p>
7633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getInputMethodMode()
7653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #show()
7663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setInputMethodMode(int mode) {
7683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setInputMethodMode(mode);
7693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
7723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Return the current value in {@link #setInputMethodMode(int)}.
7733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setInputMethodMode(int)
7753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getInputMethodMode() {
7773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getInputMethodMode();
7783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
78149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Set the selected position of the list.
78249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Only valid when {@link #isShowing()} == {@code true}.
7833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position List position to set as selected.
7853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setSelection(int position) {
7873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        DropDownListView list = mDropDownList;
7883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing() && list != null) {
7896142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            list.setListSelectionHidden(false);
7903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.setSelection(position);
79149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
79249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (Build.VERSION.SDK_INT >= 11) {
79349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) {
79449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    list.setItemChecked(position, true);
79549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
7963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
7973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
80149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Clear any current list selection.
80249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Only valid when {@link #isShowing()} == {@code true}.
8033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void clearListSelection() {
8053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final DropDownListView list = mDropDownList;
8063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (list != null) {
8073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // WARNING: Please read the comment where mListSelectionHidden is declared
8086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            list.setListSelectionHidden(true);
8093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            //list.hideSelector();
8103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.requestLayout();
8113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
8153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return {@code true} if the popup is currently showing, {@code false} otherwise.
8163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8176142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @Override
8183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isShowing() {
8193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.isShowing();
8203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
82349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return {@code true} if this popup is configured to assume the user does not need
82449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * to interact with the IME while it is showing, {@code false} otherwise.
8253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isInputMethodNotNeeded() {
8273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getInputMethodMode() == INPUT_METHOD_NOT_NEEDED;
8283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
8313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Perform an item click operation on the specified list adapter position.
8323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
8333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position Adapter position for performing the click
83449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return true if the click action could be performed, false if not.
83549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *         (e.g. if the popup was not showing, this method would return false.)
8363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean performItemClick(int position) {
8383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing()) {
8393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mItemClickListener != null) {
8403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final DropDownListView list = mDropDownList;
8413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final View child = list.getChildAt(position - list.getFirstVisiblePosition());
8423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ListAdapter adapter = list.getAdapter();
8433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mItemClickListener.onItemClick(list, child, position, adapter.getItemId(position));
8443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
8453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return true;
8463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
8483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
8513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The currently selected item or null if the popup is not showing.
8523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8536142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @Nullable Object getSelectedItem() {
8543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
8553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return null;
8563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItem();
8583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
86149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return The position of the currently selected item or {@link ListView#INVALID_POSITION}
86249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * if {@link #isShowing()} == {@code false}.
86349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
8643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedItemPosition()
8653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getSelectedItemPosition() {
8673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
8683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return ListView.INVALID_POSITION;
8693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItemPosition();
8713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
87449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID}
87549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * if {@link #isShowing()} == {@code false}.
87649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
8773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedItemId()
8783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public long getSelectedItemId() {
8803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
8813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return ListView.INVALID_ROW_ID;
8823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItemId();
8843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
88749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return The View for the currently selected item or null if
88849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * {@link #isShowing()} == {@code false}.
88949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
8903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedView()
8913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8926142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @Nullable View getSelectedView() {
8933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
8943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return null;
8953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedView();
8973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
90049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return The {@link ListView} displayed within the popup window.
90149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Only valid when {@link #isShowing()} == {@code true}.
9023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
9036142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @Override
9046142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public @Nullable ListView getListView() {
9053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList;
9063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
9073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    @NonNull DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
9096142a54baae3289f734947c6b5375b12eb0fb722Chris Banes        return new DropDownListView(context, hijackFocus);
9106142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    }
9116142a54baae3289f734947c6b5375b12eb0fb722Chris Banes
9123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
91349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * The maximum number of list items that can be visible and still have
91449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the list expand when touched.
9153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
9163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param max Max number of items that can be visible and still allow the list to expand.
9173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
9183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    void setListItemExpandMax(int max) {
9193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mListItemExpandMaximum = max;
9203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
9213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
92349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Filter key down events. By forwarding key down events to this function,
92449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * views using non-modal ListPopupWindow can have it handle key selection of items.
9253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
9263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param keyCode keyCode param passed to the host view's onKeyDown
92749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param event event param passed to the host view's onKeyDown
9283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return true if the event was handled, false if it was ignored.
92949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
9303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setModal(boolean)
9313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
9326142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
9333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // when the drop down is shown, we drive it directly
9343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing()) {
9353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // the key events are forwarded to the list in the drop down view
9363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // note that ListView handles space but we don't want that to happen
9373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // also if selection is not currently in the drop down, then don't
9383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // let center or enter presses go there since that would cause it
9393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // to select one of its items
9403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (keyCode != KeyEvent.KEYCODE_SPACE
9413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    && (mDropDownList.getSelectedItemPosition() >= 0
94249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    || !isConfirmKey(keyCode))) {
9433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int curIndex = mDropDownList.getSelectedItemPosition();
9443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                boolean consumed;
9453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final boolean below = !mPopup.isAboveAnchor();
9473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ListAdapter adapter = mAdapter;
9493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                boolean allEnabled;
9513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int firstItem = Integer.MAX_VALUE;
9523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int lastItem = Integer.MIN_VALUE;
9533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (adapter != null) {
9553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    allEnabled = adapter.areAllItemsEnabled();
9563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    firstItem = allEnabled ? 0 :
957ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            mDropDownList.lookForSelectablePosition(0, true);
9583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    lastItem = allEnabled ? adapter.getCount() - 1 :
959ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
9603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
9633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
9643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // When the selection is at the top, we block the key
9653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // event to prevent focus from moving.
9663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    clearListSelection();
9673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
9683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    show();
9693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    return true;
9703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
9713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // WARNING: Please read the comment where mListSelectionHidden
9723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    //          is declared
9736142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                    mDropDownList.setListSelectionHidden(false);
9743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                consumed = mDropDownList.onKeyDown(keyCode, event);
97749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed);
9783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (consumed) {
9803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // If it handled the key event, then the user is
9813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // navigating in the list, so we should put it in front.
9823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
9833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // Here's a little trick we need to do to make sure that
9843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // the list view is actually showing its focus indicator,
9853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // by ensuring it has focus and getting its window out
9863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // of touch mode.
9873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownList.requestFocusFromTouch();
9883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    show();
9893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    switch (keyCode) {
9913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // avoid passing the focus from the text view to the
9923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // next component
9933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_ENTER:
9943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_CENTER:
9953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_DOWN:
9963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_UP:
9973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            return true;
9983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
9993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
10003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
10013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // when the selection is at the bottom, we block the
10023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // event to avoid going to the next focusable widget
10033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        if (curIndex == lastItem) {
10043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            return true;
10053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        }
10063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP &&
10073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            curIndex == firstItem) {
10083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        return true;
10093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
10103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
10113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
10123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
10133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
10153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
10163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
101849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Filter key down events. By forwarding key up events to this function,
101949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * views using non-modal ListPopupWindow can have it handle key selection of items.
10203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
10213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param keyCode keyCode param passed to the host view's onKeyUp
102249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param event event param passed to the host view's onKeyUp
10233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return true if the event was handled, false if it was ignored.
102449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
10253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setModal(boolean)
10263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
10276142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
10283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
10293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            boolean consumed = mDropDownList.onKeyUp(keyCode, event);
103049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (consumed && isConfirmKey(keyCode)) {
103149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                // if the list accepts the key events and the key event was a click, the text view
103249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                // gets the selected item from the drop down as its content
103349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                dismiss();
10343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
10353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return consumed;
10363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
10373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
10383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
10393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
104149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Filter pre-IME key events. By forwarding {@link View#onKeyPreIme(int, KeyEvent)}
104249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * events to this function, views using ListPopupWindow can have it dismiss the popup
104349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * when the back key is pressed.
104449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
104549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param keyCode keyCode param passed to the host view's onKeyPreIme
104649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param event event param passed to the host view's onKeyPreIme
104749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return true if the event was handled, false if it was ignored.
104849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
104949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @see #setModal(boolean)
105049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
10516142a54baae3289f734947c6b5375b12eb0fb722Chris Banes    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
105249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
105349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            // special case for the back key, we do not even try to send it
105449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            // to the drop down list but instead, consume it immediately
105549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            final View anchorView = mDropDownAnchorView;
105649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
105749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
105849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (state != null) {
105949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    state.startTracking(event, this);
106049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
106149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return true;
106249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            } else if (event.getAction() == KeyEvent.ACTION_UP) {
106349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
106449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (state != null) {
106549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    state.handleUpEvent(event);
106649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
106749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                if (event.isTracking() && !event.isCanceled()) {
106849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    dismiss();
106949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                    return true;
107049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                }
107149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
107249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        }
107349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return false;
107449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
107549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
107649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
107749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Returns an {@link OnTouchListener} that can be added to the source view
107849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * to implement drag-to-open behavior. Generally, the source view should be
107949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * the same view that was passed to {@link #setAnchorView}.
108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>
108149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * When the listener is set on a view, touching that view and dragging
108249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * outside of its bounds will open the popup window. Lifting will select the
108349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * currently touched list item.
108449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>
108549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * Example usage:
108649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <pre>
108749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * ListPopupWindow myPopup = new ListPopupWindow(context);
108849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * myPopup.setAnchor(myAnchor);
108949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * OnTouchListener dragListener = myPopup.createDragToOpenListener(myAnchor);
109049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * myAnchor.setOnTouchListener(dragListener);
109149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * </pre>
109249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     *
109349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @param src the view on which the resulting listener will be set
109449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * @return a touch listener that controls drag-to-open behavior
109549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     */
109649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    public OnTouchListener createDragToOpenListener(View src) {
109749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return new ForwardingListener(src) {
109849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            @Override
109949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            public ListPopupWindow getPopup() {
110049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                return ListPopupWindow.this;
110149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes            }
110249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        };
110349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
110449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
110549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    /**
110649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * <p>Builds the popup window's content and returns the height the popup
110749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes     * should have. Returns -1 when the content already exists.</p>
11083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
11093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return the content's height or -1 if content already exists
11103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
11113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int buildDropDown() {
11123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        ViewGroup dropDownView;
11133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int otherHeights = 0;
11143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mDropDownList == null) {
11163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            Context context = mContext;
11173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            /**
11193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * This Runnable exists for the sole purpose of checking if the view layout has got
11203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * completed and if so call showDropDown to display the drop down. This is used to show
11213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * the drop down as soon as possible after user opens up the search dialog, without
11223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * waiting for the normal UI pipeline to do it's job which is slower than this method.
11233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             */
11243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mShowDropDownRunnable = new Runnable() {
11253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void run() {
11263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // View layout should be all done before displaying the drop down.
11273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    View view = getAnchorView();
11283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (view != null && view.getWindowToken() != null) {
11293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        show();
11303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
11313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
11323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            };
11333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11346142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            mDropDownList = createDropDownListView(context, !mModal);
11353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownListHighlight != null) {
11363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownList.setSelector(mDropDownListHighlight);
11373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
11383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setAdapter(mAdapter);
11393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setOnItemClickListener(mItemClickListener);
11403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setFocusable(true);
11413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setFocusableInTouchMode(true);
11426142a54baae3289f734947c6b5375b12eb0fb722Chris Banes            mDropDownList.setOnItemSelectedListener(new OnItemSelectedListener() {
11433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void onItemSelected(AdapterView<?> parent, View view,
114420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        int position, long id) {
11453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (position != -1) {
11473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        DropDownListView dropDownList = mDropDownList;
11483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        if (dropDownList != null) {
11506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes                            dropDownList.setListSelectionHidden(false);
11513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        }
11523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
11533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
11543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void onNothingSelected(AdapterView<?> parent) {
11563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
11573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            });
11583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setOnScrollListener(mScrollListener);
11593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mItemSelectedListener != null) {
11613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
11623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
11633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dropDownView = mDropDownList;
11653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            View hintView = mPromptView;
11673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (hintView != null) {
11683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // if a hint has been specified, we accomodate more space for it and
11693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // add a text view in the drop down menu, at the bottom of the list
11703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout hintContainer = new LinearLayout(context);
11713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintContainer.setOrientation(LinearLayout.VERTICAL);
11723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
117449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes                        ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f
11753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                );
11763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                switch (mPromptPosition) {
11783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case POSITION_PROMPT_BELOW:
11793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(dropDownView, hintParams);
11803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(hintView);
11813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
11823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case POSITION_PROMPT_ABOVE:
11843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(hintView);
11853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(dropDownView, hintParams);
11863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
11873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    default:
11893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        Log.e(TAG, "Invalid hint position " + mPromptPosition);
11903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
11913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
11923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
119318864e53490e04739f1063a7ee113549874f87b0Chris Banes                // Measure the hint's height to find how much more vertical
119418864e53490e04739f1063a7ee113549874f87b0Chris Banes                // space we need to add to the drop down's height.
119518864e53490e04739f1063a7ee113549874f87b0Chris Banes                final int widthSize;
119618864e53490e04739f1063a7ee113549874f87b0Chris Banes                final int widthMode;
119718864e53490e04739f1063a7ee113549874f87b0Chris Banes                if (mDropDownWidth >= 0) {
119818864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthMode = MeasureSpec.AT_MOST;
119918864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthSize = mDropDownWidth;
120018864e53490e04739f1063a7ee113549874f87b0Chris Banes                } else {
120118864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthMode = MeasureSpec.UNSPECIFIED;
120218864e53490e04739f1063a7ee113549874f87b0Chris Banes                    widthSize = 0;
120318864e53490e04739f1063a7ee113549874f87b0Chris Banes                }
120418864e53490e04739f1063a7ee113549874f87b0Chris Banes                final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
120518864e53490e04739f1063a7ee113549874f87b0Chris Banes                final int heightSpec = MeasureSpec.UNSPECIFIED;
12063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintView.measure(widthSpec, heightSpec);
12073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
12093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin
12103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        + hintParams.bottomMargin;
12113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                dropDownView = hintContainer;
12133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setContentView(dropDownView);
12163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
12173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dropDownView = (ViewGroup) mPopup.getContentView();
12183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final View view = mPromptView;
12193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (view != null) {
12203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout.LayoutParams hintParams =
12213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        (LinearLayout.LayoutParams) view.getLayoutParams();
12223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                otherHeights = view.getMeasuredHeight() + hintParams.topMargin
12233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        + hintParams.bottomMargin;
12243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // getMaxAvailableHeight() subtracts the padding, so we put it back
122876ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        // to get the available height for the whole window.
122976ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        final int padding;
123076ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        final Drawable background = mPopup.getBackground();
12313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (background != null) {
12323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            background.getPadding(mTempRect);
12333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            padding = mTempRect.top + mTempRect.bottom;
12343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
123576ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette            // If we don't have an explicit vertical offset, determine one from
123676ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette            // the window background so that content will line up.
12373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mDropDownVerticalOffsetSet) {
12383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownVerticalOffset = -mTempRect.top;
12393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
12413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mTempRect.setEmpty();
124276ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette            padding = 0;
12433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // Max height available on the screen for a popup.
12467ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        final boolean ignoreBottomDecorations =
12473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
12487ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        final int maxHeight = getMaxAvailableHeight(getAnchorView(), mDropDownVerticalOffset,
12497ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                ignoreBottomDecorations);
1250a2c72b87007d10202c25e78e904938f770c6337dChris Banes        if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
12513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return maxHeight + padding;
12523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int childWidthSpec;
12553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        switch (mDropDownWidth) {
12563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            case ViewGroup.LayoutParams.WRAP_CONTENT:
12573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(
125876ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette                        mContext.getResources().getDisplayMetrics().widthPixels
125976ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette                                - (mTempRect.left + mTempRect.right),
12603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        MeasureSpec.AT_MOST);
12613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
1262a2c72b87007d10202c25e78e904938f770c6337dChris Banes            case ViewGroup.LayoutParams.MATCH_PARENT:
12633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(
126476ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette                        mContext.getResources().getDisplayMetrics().widthPixels
126576ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette                                - (mTempRect.left + mTempRect.right),
12663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        MeasureSpec.EXACTLY);
12673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
12683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            default:
12693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY);
12703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
12713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
1272ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
127376ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        // Add padding only if the list has items in it, that way we don't show
127476ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        // the popup if it is not needed.
127579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int listContent = mDropDownList.measureHeightOfChildrenCompat(childWidthSpec,
12763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                0, DropDownListView.NO_POSITION, maxHeight - otherHeights, -1);
127776ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        if (listContent > 0) {
127876ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette            final int listPadding = mDropDownList.getPaddingTop()
127976ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette                    + mDropDownList.getPaddingBottom();
128076ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette            otherHeights += padding + listPadding;
128176ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette        }
12823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return listContent + otherHeights;
12843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
12853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupDataSetObserver extends DataSetObserver {
12873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onChanged() {
12893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (isShowing()) {
12903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // Resize the popup to fit new content
12913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                show();
12923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onInvalidated() {
12973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dismiss();
12983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class ListSelectorHider implements Runnable {
13023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void run() {
13033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            clearListSelection();
13043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class ResizePopupRunnable implements Runnable {
13083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void run() {
130918864e53490e04739f1063a7ee113549874f87b0Chris Banes            if (mDropDownList != null && ViewCompat.isAttachedToWindow(mDropDownList)
131018864e53490e04739f1063a7ee113549874f87b0Chris Banes                    && mDropDownList.getCount() > mDropDownList.getChildCount()
131118864e53490e04739f1063a7ee113549874f87b0Chris Banes                    && mDropDownList.getChildCount() <= mListItemExpandMaximum) {
13123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
13133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                show();
13143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
13153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupTouchInterceptor implements OnTouchListener {
13193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean onTouch(View v, MotionEvent event) {
13203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int action = event.getAction();
13213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int x = (int) event.getX();
13223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int y = (int) event.getY();
13233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (action == MotionEvent.ACTION_DOWN &&
13253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup != null && mPopup.isShowing() &&
13263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) {
13273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT);
13283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (action == MotionEvent.ACTION_UP) {
13293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.removeCallbacks(mResizePopupRunnable);
13303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
13313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return false;
13323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupScrollListener implements ListView.OnScrollListener {
13363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
133720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                int totalItemCount) {
13383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onScrollStateChanged(AbsListView view, int scrollState) {
13423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (scrollState == SCROLL_STATE_TOUCH_SCROLL &&
13433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    !isInputMethodNotNeeded() && mPopup.getContentView() != null) {
13443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.removeCallbacks(mResizePopupRunnable);
13453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mResizePopupRunnable.run();
13463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
13473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
134949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
135049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    private static boolean isConfirmKey(int keyCode) {
135149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes        return keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_CENTER;
135249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes    }
135349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes
1354ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    private void setPopupClipToScreenEnabled(boolean clip) {
1355ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        if (sClipToWindowEnabledMethod != null) {
1356ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            try {
1357ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                sClipToWindowEnabledMethod.invoke(mPopup, clip);
1358ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            } catch (Exception e) {
1359ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes                Log.i(TAG, "Could not call setClipToScreenEnabled() on PopupWindow. Oh well.");
1360ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes            }
1361ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes        }
1362ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes    }
1363ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes
13647ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes    private int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) {
13657ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        if (sGetMaxAvailableHeightMethod != null) {
13667ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes            try {
13677ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                return (int) sGetMaxAvailableHeightMethod.invoke(mPopup, anchor, yOffset,
13687ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                        ignoreBottomDecorations);
13697ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes            } catch (Exception e) {
13707ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                Log.i(TAG, "Could not call getMaxAvailableHeightMethod(View, int, boolean)"
13717ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes                        + " on PopupWindow. Using the public version.");
13727ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes            }
13737ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        }
13747ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes        return mPopup.getMaxAvailableHeight(anchor, yOffset);
13757ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes    }
13763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani}