1c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell/*
2c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Copyright (C) 2010 The Android Open Source Project
3c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
4c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Licensed under the Apache License, Version 2.0 (the "License");
5c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * you may not use this file except in compliance with the License.
6c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * You may obtain a copy of the License at
7c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
8c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *      http://www.apache.org/licenses/LICENSE-2.0
9c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
10c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Unless required by applicable law or agreed to in writing, software
11c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * distributed under the License is distributed on an "AS IS" BASIS,
12c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * See the License for the specific language governing permissions and
14c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * limitations under the License.
15c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */
16c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
17c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellpackage android.widget;
18c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1902cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport com.android.internal.R;
2002cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport com.android.internal.view.menu.ShowableListMenu;
2102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette
2202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport android.annotation.AttrRes;
2302cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport android.annotation.NonNull;
2402cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport android.annotation.Nullable;
2502cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport android.annotation.StyleRes;
26c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.content.Context;
27f023c2530a4591889dda614aaa016d5a9f9617edAlan Viveretteimport android.content.res.TypedArray;
28c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.database.DataSetObserver;
29c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.graphics.Rect;
30c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.graphics.drawable.Drawable;
31c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.os.Handler;
32c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.util.AttributeSet;
33c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.util.Log;
3454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powellimport android.view.Gravity;
35c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.KeyEvent;
36c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.MotionEvent;
37c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View;
38c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View.MeasureSpec;
39c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View.OnTouchListener;
40711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunneimport android.view.ViewGroup;
41711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunneimport android.view.ViewParent;
4280ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viveretteimport android.view.WindowManager;
4302cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viveretteimport android.widget.AdapterView.OnItemSelectedListener;
441d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio
45c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell/**
46c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * A ListPopupWindow anchors itself to a host view and displays a
4765d79fbe55c017edd9419ddb71939c8916471390Adam Powell * list of choices.
48c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
49c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * <p>ListPopupWindow contains a number of tricky behaviors surrounding
50c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * positioning, scrolling parents to fit the dropdown, interacting
51c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * sanely with the IME if present, and others.
52c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
53c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @see android.widget.AutoCompleteTextView
54c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @see android.widget.Spinner
55c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */
56f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasbergpublic class ListPopupWindow implements ShowableListMenu {
57c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final String TAG = "ListPopupWindow";
58c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final boolean DEBUG = false;
59c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
60c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
61c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * This value controls the length of time that the user
62c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * must leave a pointer down without scrolling to expand
63c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the autocomplete dropdown list to cover the IME.
64c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
65c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final int EXPAND_LIST_TIMEOUT = 250;
66c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
67c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Context mContext;
68c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private ListAdapter mAdapter;
69c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private DropDownListView mDropDownList;
70c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
71c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
72c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
73c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownHorizontalOffset;
74c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownVerticalOffset;
7580ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette    private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
768132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell    private boolean mDropDownVerticalOffsetSet;
7791098574f90277128415e9593cce1e495cc51465Alan Viverette    private boolean mIsAnimatedFromAnchor = true;
78c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
7954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private int mDropDownGravity = Gravity.NO_GRAVITY;
8054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
81c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mDropDownAlwaysVisible = false;
82c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mForceIgnoreOutsideTouch = false;
83348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    int mListItemExpandMaximum = Integer.MAX_VALUE;
84c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
85c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private View mPromptView;
86c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mPromptPosition = POSITION_PROMPT_ABOVE;
87c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
88c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private DataSetObserver mObserver;
89c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
90c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private View mDropDownAnchorView;
91c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
92c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Drawable mDropDownListHighlight;
93c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
94c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private AdapterView.OnItemClickListener mItemClickListener;
95c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private AdapterView.OnItemSelectedListener mItemSelectedListener;
96c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
974267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable();
98c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor();
99c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final PopupScrollListener mScrollListener = new PopupScrollListener();
100c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final ListSelectorHider mHideSelector = new ListSelectorHider();
101c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Runnable mShowDropDownRunnable;
102c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1034a50723fe399047e833e61f43928f21d90e2b5faAlan Viverette    private final Handler mHandler;
104c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
10591098574f90277128415e9593cce1e495cc51465Alan Viverette    private final Rect mTempRect = new Rect();
10691098574f90277128415e9593cce1e495cc51465Alan Viverette
10791098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
10891098574f90277128415e9593cce1e495cc51465Alan Viverette     * Optional anchor-relative bounds to be used as the transition epicenter.
10991098574f90277128415e9593cce1e495cc51465Alan Viverette     * When {@code null}, the anchor bounds are used as the epicenter.
11091098574f90277128415e9593cce1e495cc51465Alan Viverette     */
11191098574f90277128415e9593cce1e495cc51465Alan Viverette    private Rect mEpicenterBounds;
112c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
113c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mModal;
114c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1158e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg    PopupWindow mPopup;
1168e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg
117c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
118c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The provided prompt view should appear above list content.
119c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
120c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptPosition(int)
121c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getPromptPosition()
122c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptView(View)
123c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
124c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int POSITION_PROMPT_ABOVE = 0;
125c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
126c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
127c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The provided prompt view should appear below list content.
128c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
129c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptPosition(int)
130c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getPromptPosition()
131c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptView(View)
132c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
133c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int POSITION_PROMPT_BELOW = 1;
134c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
135c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
136c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Alias for {@link ViewGroup.LayoutParams#MATCH_PARENT}.
137c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup width, the popup will match the width of the anchor view.
138c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup height, the popup will fill available space.
139c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
140c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT;
141c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
142c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
143c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
144c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup width, the popup will use the width of its content.
145c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
146c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
147c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
148c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
149c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
150c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * input method should be based on the focusability of the popup.  That is
151c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if it is focusable than it needs to work with the input method, else
152c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * it doesn't.
153c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
154c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE;
155c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
156c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
157c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
158c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * work with an input method, regardless of whether it is focusable.  This
159c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * means that it will always be displayed so that the user can also operate
160c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the input method while it is shown.
161c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
162c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED;
163c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
164c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
165c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
166c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * work with an input method, regardless of whether it is focusable.  This
167c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * means that it will always be displayed to use as much space on the
168c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * screen as needed, regardless of whether this covers the input method.
169c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
170c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_NOT_NEEDED = PopupWindow.INPUT_METHOD_NOT_NEEDED;
171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
172c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
174c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
176c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
177c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
17802cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public ListPopupWindow(@NonNull Context context) {
179c2238d006237ebf1296074d80fb4f4a2741ef880Daniel Lehmann        this(context, null, com.android.internal.R.attr.listPopupWindowStyle, 0);
180c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
181c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
182c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
183c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
184c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
185c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
186c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
187c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
188c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
18902cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs) {
1900b2d306e7000f4c0c6ad4e00d494bb401d8a9fc2Adam Powell        this(context, attrs, com.android.internal.R.attr.listPopupWindowStyle, 0);
191c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
192c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
193c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
194c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
195c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
196c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
197c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
198c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
199c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleAttr Default style attribute to use for popup content.
200c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
20102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
20202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette            @AttrRes int defStyleAttr) {
203c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        this(context, attrs, defStyleAttr, 0);
204c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
205c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
206c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
207c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
208c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
209c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
210c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
211c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
212c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleAttr Style attribute to read for default styling of popup content.
213c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleRes Style resource ID to use for default styling of popup content.
214c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
21502cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
21602cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
217c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mContext = context;
2184a50723fe399047e833e61f43928f21d90e2b5faAlan Viverette        mHandler = new Handler(context.getMainLooper());
219f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette
220f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPopupWindow,
221f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette                defStyleAttr, defStyleRes);
222f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        mDropDownHorizontalOffset = a.getDimensionPixelOffset(
223f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette                R.styleable.ListPopupWindow_dropDownHorizontalOffset, 0);
224f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        mDropDownVerticalOffset = a.getDimensionPixelOffset(
225f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette                R.styleable.ListPopupWindow_dropDownVerticalOffset, 0);
226f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        if (mDropDownVerticalOffset != 0) {
227f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette            mDropDownVerticalOffsetSet = true;
228f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        }
229f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette        a.recycle();
230f023c2530a4591889dda614aaa016d5a9f9617edAlan Viverette
231c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
2326f5e934b96c400f610b1c5ad228cc60cab5d443fAdam Powell        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
233c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
234c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
235c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
236c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the adapter that provides the data and the views to represent the data
237c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * in this popup window.
238c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
239c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param adapter The adapter to use to create this window's content.
240c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
24102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setAdapter(@Nullable ListAdapter adapter) {
242c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mObserver == null) {
243c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mObserver = new PopupDataSetObserver();
244c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else if (mAdapter != null) {
24599969da3772d9a0f5079672847ca4f2ad819c1bbAdam Powell            mAdapter.unregisterDataSetObserver(mObserver);
246c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
247c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mAdapter = adapter;
248c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mAdapter != null) {
249c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            adapter.registerDataSetObserver(mObserver);
250c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
251c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
252c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownList != null) {
253c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setAdapter(mAdapter);
254c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
255c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
256c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
257c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
258c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set where the optional prompt view should appear. The default is
259c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #POSITION_PROMPT_ABOVE}.
260c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
261c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position A position constant declaring where the prompt should be displayed.
262c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
263c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_ABOVE
264c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_BELOW
265c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
266c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setPromptPosition(int position) {
267c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPromptPosition = position;
268c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
269c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
270c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
271c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Where the optional prompt view should appear.
272c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
273c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_ABOVE
274c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_BELOW
275c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
276c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getPromptPosition() {
277c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPromptPosition;
278c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
279c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
280c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
281c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set whether this window should be modal when shown.
282c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
283c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>If a popup window is modal, it will receive all touch and key input.
284c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If the user touches outside the popup window's content area the popup window
285c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * will be dismissed.
286c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
287c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param modal {@code true} if the popup window should be modal, {@code false} otherwise.
288c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
289c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setModal(boolean modal) {
290e04499ad930ff4f112114683dc9f1e5411d6802bChet Haase        mModal = modal;
291c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setFocusable(modal);
292c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
293c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
294c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
295c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns whether the popup window will be modal when shown.
296c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
297c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if the popup window will be modal, {@code false} otherwise.
298c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
299c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isModal() {
300c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mModal;
301c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
302c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
303c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
304c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
305c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
306c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * ignore outside touch even when the drop down is not set to always visible.
307c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
308c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Used only by AutoCompleteTextView to handle some internal special cases.
309c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
310c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
311c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
312c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
313c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
314c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
315c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets whether the drop-down should remain visible under certain conditions.
316c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
317c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless
318c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * of the size or content of the list.  {@link #getBackground()} will fill any space
319c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * that is not used by the list.
320c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
321c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
322c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
323c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Only used by AutoCompleteTextView under special conditions.
324c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
325c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
326c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownAlwaysVisible = dropDownAlwaysVisible;
327c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
328c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
329c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
330c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Whether the drop-down is visible under special conditions.
331c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
332c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Only used by AutoCompleteTextView under special conditions.
333c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
334c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isDropDownAlwaysVisible() {
335c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownAlwaysVisible;
336c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
337c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
338c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
339c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the operating mode for the soft input area.
340c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
341c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param mode The desired mode, see
342c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
343c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *        for the full list
344c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
345c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see android.view.WindowManager.LayoutParams#softInputMode
346c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getSoftInputMode()
347c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
348c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setSoftInputMode(int mode) {
349c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setSoftInputMode(mode);
350c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
351c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
352c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
353c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the current value in {@link #setSoftInputMode(int)}.
354c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
355c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setSoftInputMode(int)
356c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see android.view.WindowManager.LayoutParams#softInputMode
357c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
358c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getSoftInputMode() {
359c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getSoftInputMode();
360c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
361c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
362c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
363c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a drawable to use as the list item selector.
364c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
365c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param selector List selector drawable to use in the popup.
366c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
367c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setListSelector(Drawable selector) {
368c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownListHighlight = selector;
369c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
370c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
371c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
372c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The background drawable for the popup window.
373c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
37402cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @Nullable Drawable getBackground() {
375c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getBackground();
376c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
377c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
378c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
379c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a drawable to be the background for the popup window.
380c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
381c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param d A drawable to set as the background.
382c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
38302cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setBackgroundDrawable(@Nullable Drawable d) {
384c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setBackgroundDrawable(d);
385c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
386c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
387c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
388c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set an animation style to use when the popup window is shown or dismissed.
389c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
390c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param animationStyle Animation style to use.
391c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
39202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setAnimationStyle(@StyleRes int animationStyle) {
393c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setAnimationStyle(animationStyle);
394c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
395c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
396c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
397c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the animation style that will be used when the popup window is
398c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * shown or dismissed.
399c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
400c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Animation style that will be used.
401c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
40202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @StyleRes int getAnimationStyle() {
403c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getAnimationStyle();
404c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
405c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
406c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
407c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the view that will be used to anchor this popup.
408c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
409c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The popup's anchor view
410c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
41102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @Nullable View getAnchorView() {
412c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownAnchorView;
413c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
414c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
415c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
416c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the popup's anchor view. This popup will always be positioned relative to
417c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the anchor view when shown.
418c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
419c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param anchor The view to use as an anchor.
420c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
42102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setAnchorView(@Nullable View anchor) {
422c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownAnchorView = anchor;
423c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
424c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
425c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
426c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The horizontal offset of the popup from its anchor in pixels.
427c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
428c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getHorizontalOffset() {
429c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownHorizontalOffset;
430c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
431c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
432c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
433c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the horizontal offset of this popup from its anchor view in pixels.
434c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
435a984b38df5cfe6db0ba792bf2a6221f6b6072448Adam Powell     * @param offset The horizontal offset of the popup from its anchor.
436c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
437c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setHorizontalOffset(int offset) {
438c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownHorizontalOffset = offset;
439c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
440c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
441c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
442c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The vertical offset of the popup from its anchor in pixels.
443c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
444c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getVerticalOffset() {
4458132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        if (!mDropDownVerticalOffsetSet) {
4468132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            return 0;
4478132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        }
448c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownVerticalOffset;
449c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
450c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
451c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
452c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the vertical offset of this popup from its anchor view in pixels.
453c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
454a984b38df5cfe6db0ba792bf2a6221f6b6072448Adam Powell     * @param offset The vertical offset of the popup from its anchor.
455c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
456c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setVerticalOffset(int offset) {
457c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownVerticalOffset = offset;
4588132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        mDropDownVerticalOffsetSet = true;
459c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
460c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
461c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
46291098574f90277128415e9593cce1e495cc51465Alan Viverette     * Specifies the anchor-relative bounds of the popup's transition
46391098574f90277128415e9593cce1e495cc51465Alan Viverette     * epicenter.
46491098574f90277128415e9593cce1e495cc51465Alan Viverette     *
46591098574f90277128415e9593cce1e495cc51465Alan Viverette     * @param bounds anchor-relative bounds
46691098574f90277128415e9593cce1e495cc51465Alan Viverette     * @hide
46791098574f90277128415e9593cce1e495cc51465Alan Viverette     */
46891098574f90277128415e9593cce1e495cc51465Alan Viverette    public void setEpicenterBounds(Rect bounds) {
46991098574f90277128415e9593cce1e495cc51465Alan Viverette        mEpicenterBounds = bounds;
47091098574f90277128415e9593cce1e495cc51465Alan Viverette    }
47191098574f90277128415e9593cce1e495cc51465Alan Viverette
47291098574f90277128415e9593cce1e495cc51465Alan Viverette    /**
47354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * Set the gravity of the dropdown list. This is commonly used to
47454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * set gravity to START or END for alignment with the anchor.
47554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
47654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param gravity Gravity value to use
47754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     */
47854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void setDropDownGravity(int gravity) {
47954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mDropDownGravity = gravity;
48054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
48154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
48254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    /**
483c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The width of the popup window in pixels.
484c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
485c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getWidth() {
486c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownWidth;
487c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
488c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
489c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
490c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the width of the popup window in pixels. Can also be {@link #MATCH_PARENT}
491c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * or {@link #WRAP_CONTENT}.
492c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
493c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param width Width of the popup window.
494c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
495c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setWidth(int width) {
496c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownWidth = width;
497c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
498c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
499c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
5004267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * Sets the width of the popup window by the size of its content. The final width may be
5014267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * larger to accommodate styled window dressing.
5024267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     *
5034267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * @param width Desired width of content in pixels.
5044267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     */
5054267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public void setContentWidth(int width) {
5064267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        Drawable popupBackground = mPopup.getBackground();
5074267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        if (popupBackground != null) {
508a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            popupBackground.getPadding(mTempRect);
509a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            mDropDownWidth = mTempRect.left + mTempRect.right + width;
51062e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        } else {
51162e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell            setWidth(width);
5124267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        }
5134267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
5144267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
5154267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    /**
516c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The height of the popup window in pixels.
517c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
518c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getHeight() {
519c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownHeight;
520c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
521c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
522c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
523c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}.
524c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
525c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param height Height of the popup window.
526c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
527c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setHeight(int height) {
528c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownHeight = height;
529c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
530c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
531c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
53280ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * Set the layout type for this popup window.
53380ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * <p>
53480ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * See {@link WindowManager.LayoutParams#type} for possible values.
53580ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     *
53680ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * @param layoutType Layout type for this window.
53780ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     *
53880ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     * @see WindowManager.LayoutParams#type
53980ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette     */
54080ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette    public void setWindowLayoutType(int layoutType) {
54180ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette        mDropDownWindowLayoutType = layoutType;
54280ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette    }
54380ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette
54480ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette    /**
545c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a listener to receive events when a list item is clicked.
546c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
547c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param clickListener Listener to register
548c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
549c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
550c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
55102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) {
552c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mItemClickListener = clickListener;
553c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
554c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
555c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
556c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a listener to receive events when a list item is selected.
557c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
558c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param selectedListener Listener to register.
559c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
56002cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette     * @see ListView#setOnItemSelectedListener(OnItemSelectedListener)
561c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
56202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) {
563c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mItemSelectedListener = selectedListener;
564c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
565c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
566c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
567c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set a view to act as a user prompt for this popup window. Where the prompt view will appear
568c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * is controlled by {@link #setPromptPosition(int)}.
569c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
570c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param prompt View to use as an informational prompt.
571c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
57202cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setPromptView(@Nullable View prompt) {
573c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        boolean showing = isShowing();
574c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (showing) {
575c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            removePromptView();
576c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
577c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPromptView = prompt;
578c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (showing) {
579c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            show();
580c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
581c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
582c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
583c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
584c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Post a {@link #show()} call to the UI thread.
585c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
586c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void postShow() {
587c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mHandler.post(mShowDropDownRunnable);
588c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
589c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
590c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
591c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Show the popup list. If the list is already showing, this method
592c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * will recalculate the popup's size and position.
593c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
594f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg    @Override
595c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void show() {
596c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int height = buildDropDown();
597c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
59880ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette        final boolean noInputMethod = isInputMethodNotNeeded();
599348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mPopup.setAllowScrollingAnchorParent(!noInputMethod);
60080ebe0d4ecb36d0e82dce499ccc0810cf3a0ec89Alan Viverette        mPopup.setWindowLayoutType(mDropDownWindowLayoutType);
601c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
602c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mPopup.isShowing()) {
603259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            final int widthSpec;
604c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
605c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // The call to PopupWindow's update method below can accept -1 for any
606c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // value you do not want to update.
607c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = -1;
608c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
609c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = getAnchorView().getWidth();
610c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
611c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = mDropDownWidth;
612c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
613c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
614259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            final int heightSpec;
615c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
616c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // The call to PopupWindow's update method below can accept -1 for any
617c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // value you do not want to update.
618c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT;
619c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (noInputMethod) {
620259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
621259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                            ViewGroup.LayoutParams.MATCH_PARENT : 0);
622259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    mPopup.setHeight(0);
623c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
624259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
625259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                                    ViewGroup.LayoutParams.MATCH_PARENT : 0);
626259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    mPopup.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
627c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
628c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
629c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = height;
630c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
631c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = mDropDownHeight;
632c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
633c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
634c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
635c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
636c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
6370eaec1f5d1b47739b8d33cb45111bccd18f2d7b1Jun Mukai                            mDropDownVerticalOffset, (widthSpec < 0)? -1 : widthSpec,
6380eaec1f5d1b47739b8d33cb45111bccd18f2d7b1Jun Mukai                            (heightSpec < 0)? -1 : heightSpec);
639c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else {
640259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            final int widthSpec;
641c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
642c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = ViewGroup.LayoutParams.MATCH_PARENT;
643c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
644c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
645259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    widthSpec = getAnchorView().getWidth();
646c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
647259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    widthSpec = mDropDownWidth;
648c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
649c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
650c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
651259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            final int heightSpec;
652c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
653c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = ViewGroup.LayoutParams.MATCH_PARENT;
654c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
655c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
656259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    heightSpec = height;
657c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
658259c2840691a79634ffd8f63291ec21c21819542Alan Viverette                    heightSpec = mDropDownHeight;
659c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
660c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
661c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
662259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            mPopup.setWidth(widthSpec);
663259c2840691a79634ffd8f63291ec21c21819542Alan Viverette            mPopup.setHeight(heightSpec);
66456c2d337e02a275397fc9d0460dca90977f199acAdam Powell            mPopup.setClipToScreenEnabled(true);
665c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
666c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // use outside touchable to dismiss drop down when touching outside of it, so
667c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // only set this if the dropdown is not always visible
668c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
669c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setTouchInterceptor(mTouchInterceptor);
67091098574f90277128415e9593cce1e495cc51465Alan Viverette            mPopup.setEpicenterBounds(mEpicenterBounds);
671560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette            mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
672560f17098f90b15c8894cce127f2fed85f7aeb6bAlan Viverette                    mDropDownVerticalOffset, mDropDownGravity);
673c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setSelection(ListView.INVALID_POSITION);
674c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
675c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (!mModal || mDropDownList.isInTouchMode()) {
676c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                clearListSelection();
677c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
678c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (!mModal) {
679c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.post(mHideSelector);
680c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
681c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
682c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
683c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
684c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
685c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Dismiss the popup window.
686c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
687f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg    @Override
688c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void dismiss() {
689c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.dismiss();
690c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        removePromptView();
691c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setContentView(null);
692c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownList = null;
693ca51e8788a58f2af3525b7214a675f2d0233e5daAdam Powell        mHandler.removeCallbacks(mResizePopupRunnable);
694c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
695c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
6966c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    /**
6976c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     * Set a listener to receive a callback when the popup is dismissed.
6986c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     *
6996c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     * @param listener Listener that will be notified when the popup is dismissed.
7006c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     */
70102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public void setOnDismissListener(@Nullable PopupWindow.OnDismissListener listener) {
7026c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        mPopup.setOnDismissListener(listener);
7036c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    }
7046c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
705c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private void removePromptView() {
706c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mPromptView != null) {
707c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final ViewParent parent = mPromptView.getParent();
708c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (parent instanceof ViewGroup) {
709c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final ViewGroup group = (ViewGroup) parent;
710c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                group.removeView(mPromptView);
711c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
712c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
713c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
714c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
715c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
716c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Control how the popup operates with an input method: one of
717c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
718c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * or {@link #INPUT_METHOD_NOT_NEEDED}.
719c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
720c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>If the popup is showing, calling this method will take effect only
721c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the next time the popup is shown or through a manual call to the {@link #show()}
722c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * method.</p>
723c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
724c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getInputMethodMode()
725c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #show()
726c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
727c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setInputMethodMode(int mode) {
728c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setInputMethodMode(mode);
729c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
730c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
731c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
732c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Return the current value in {@link #setInputMethodMode(int)}.
733c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
734c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setInputMethodMode(int)
735c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
736c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getInputMethodMode() {
737c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getInputMethodMode();
738c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
739c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
740c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
741c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the selected position of the list.
742c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
743c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
744c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position List position to set as selected.
745c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
746c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setSelection(int position) {
747c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        DropDownListView list = mDropDownList;
748c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing() && list != null) {
749f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg            list.setListSelectionHidden(false);
750c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.setSelection(position);
751c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) {
752c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                list.setItemChecked(position, true);
753c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
754c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
755c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
756c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
757c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
758c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Clear any current list selection.
759c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
760c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
761c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void clearListSelection() {
762c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        final DropDownListView list = mDropDownList;
763c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (list != null) {
764c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // WARNING: Please read the comment where mListSelectionHidden is declared
765f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg            list.setListSelectionHidden(true);
766c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.hideSelector();
767c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.requestLayout();
768c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
769c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
770c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
771c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
772c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if the popup is currently showing, {@code false} otherwise.
773c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
774f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg    @Override
775c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isShowing() {
776c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.isShowing();
777c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
778c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
779c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
780c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if this popup is configured to assume the user does not need
781c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * to interact with the IME while it is showing, {@code false} otherwise.
782c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
783c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isInputMethodNotNeeded() {
784c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getInputMethodMode() == INPUT_METHOD_NOT_NEEDED;
785c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
786c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
787c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
788c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Perform an item click operation on the specified list adapter position.
789c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
790c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position Adapter position for performing the click
791c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the click action could be performed, false if not.
792c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *         (e.g. if the popup was not showing, this method would return false.)
793c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
794c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean performItemClick(int position) {
795c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing()) {
796c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mItemClickListener != null) {
797c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final DropDownListView list = mDropDownList;
798c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final View child = list.getChildAt(position - list.getFirstVisiblePosition());
799cdee446075811e871fc2af295377bd99c100d16dAdam Powell                final ListAdapter adapter = list.getAdapter();
800cdee446075811e871fc2af295377bd99c100d16dAdam Powell                mItemClickListener.onItemClick(list, child, position, adapter.getItemId(position));
801c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
802c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return true;
803c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
804c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
805c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
806c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
807c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
808c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The currently selected item or null if the popup is not showing.
809c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
81002cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @Nullable Object getSelectedItem() {
811c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
812c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return null;
813c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
814c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItem();
815c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
816c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
817c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
818c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The position of the currently selected item or {@link ListView#INVALID_POSITION}
819c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if {@link #isShowing()} == {@code false}.
820c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
821c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedItemPosition()
822c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
823c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getSelectedItemPosition() {
824c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
825c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return ListView.INVALID_POSITION;
826c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
827c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItemPosition();
828c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
829c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
830c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
831c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID}
832c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if {@link #isShowing()} == {@code false}.
833c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
834c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedItemId()
835c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
836c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public long getSelectedItemId() {
837c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
838c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return ListView.INVALID_ROW_ID;
839c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
840c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItemId();
841c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
842c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
843c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
844c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The View for the currently selected item or null if
845c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #isShowing()} == {@code false}.
846c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
847c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedView()
848c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
84902cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @Nullable View getSelectedView() {
850c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
851c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return null;
852c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
853c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedView();
854c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
855c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
856c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
857c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The {@link ListView} displayed within the popup window.
858c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
859c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
860f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg    @Override
86102cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public @Nullable ListView getListView() {
862c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList;
863c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
864c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
86502cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    @NonNull DropDownListView createDropDownListView(Context context, boolean hijackFocus) {
86631f581c5a64320d9a90ce3fb1a4625f94f4f8021Jun Mukai        return new DropDownListView(context, hijackFocus);
86731f581c5a64320d9a90ce3fb1a4625f94f4f8021Jun Mukai    }
86831f581c5a64320d9a90ce3fb1a4625f94f4f8021Jun Mukai
869c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
870348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * The maximum number of list items that can be visible and still have
871348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * the list expand when touched.
872348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     *
873348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * @param max Max number of items that can be visible and still allow the list to expand.
874348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     */
875348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    void setListItemExpandMax(int max) {
876348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mListItemExpandMaximum = max;
877348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    }
878348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell
879348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    /**
8808d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown     * Filter key down events. By forwarding key down events to this function,
881c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * views using non-modal ListPopupWindow can have it handle key selection of items.
8823d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
883c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyDown
884c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyDown
885c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
8863d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
887c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
8883d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     * @see #onKeyUp(int, KeyEvent)
889c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
89002cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
891c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        // when the drop down is shown, we drive it directly
892c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing()) {
893c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // the key events are forwarded to the list in the drop down view
894c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // note that ListView handles space but we don't want that to happen
895c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // also if selection is not currently in the drop down, then don't
896c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // let center or enter presses go there since that would cause it
897c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // to select one of its items
898c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (keyCode != KeyEvent.KEYCODE_SPACE
899c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    && (mDropDownList.getSelectedItemPosition() >= 0
90024d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                            || !KeyEvent.isConfirmKey(keyCode))) {
901c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int curIndex = mDropDownList.getSelectedItemPosition();
902c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                boolean consumed;
903c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
904c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final boolean below = !mPopup.isAboveAnchor();
905c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
906c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final ListAdapter adapter = mAdapter;
907c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
908c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                boolean allEnabled;
909c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int firstItem = Integer.MAX_VALUE;
910c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int lastItem = Integer.MIN_VALUE;
911c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
912c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (adapter != null) {
913c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    allEnabled = adapter.areAllItemsEnabled();
914c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    firstItem = allEnabled ? 0 :
915c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownList.lookForSelectablePosition(0, true);
916c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    lastItem = allEnabled ? adapter.getCount() - 1 :
917c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
918c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
919c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
920c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
921c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
922c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // When the selection is at the top, we block the key
923c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // event to prevent focus from moving.
924c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    clearListSelection();
925c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
926c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    show();
927c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    return true;
928c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
929c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // WARNING: Please read the comment where mListSelectionHidden
930c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    //          is declared
931f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg                    mDropDownList.setListSelectionHidden(false);
932c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
933c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
934c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                consumed = mDropDownList.onKeyDown(keyCode, event);
935c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed);
936c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
937c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (consumed) {
938c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // If it handled the key event, then the user is
939c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // navigating in the list, so we should put it in front.
940c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
941c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // Here's a little trick we need to do to make sure that
942c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // the list view is actually showing its focus indicator,
943c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // by ensuring it has focus and getting its window out
944c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // of touch mode.
945c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mDropDownList.requestFocusFromTouch();
946c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    show();
947c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
948c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    switch (keyCode) {
949c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // avoid passing the focus from the text view to the
950c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // next component
951c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_ENTER:
952c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_CENTER:
953c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_DOWN:
954c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_UP:
955c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            return true;
956c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
957c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
958c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
959c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // when the selection is at the bottom, we block the
960c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // event to avoid going to the next focusable widget
961c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        if (curIndex == lastItem) {
962c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            return true;
963c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        }
964c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP &&
965c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            curIndex == firstItem) {
966c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        return true;
967c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
968c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
969c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
970c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
971c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
972c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
973c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
974c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
975c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
9763d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     * Filter key up events. By forwarding key up events to this function,
977c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * views using non-modal ListPopupWindow can have it handle key selection of items.
9783d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
979c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyUp
980c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyUp
981c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
9823d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
983c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
9843d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     * @see #onKeyDown(int, KeyEvent)
985c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
98602cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
987c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
988c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            boolean consumed = mDropDownList.onKeyUp(keyCode, event);
98924d36f592224d1316165f579bb0937df0bf42f7cMichael Wright            if (consumed && KeyEvent.isConfirmKey(keyCode)) {
99024d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                // if the list accepts the key events and the key event was a click, the text view
99124d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                // gets the selected item from the drop down as its content
99224d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                dismiss();
993c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
994c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return consumed;
995c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
996c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
997c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
998c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
999c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
1000c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Filter pre-IME key events. By forwarding {@link View#onKeyPreIme(int, KeyEvent)}
1001c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * events to this function, views using ListPopupWindow can have it dismiss the popup
1002c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * when the back key is pressed.
10033d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
1004c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyPreIme
1005c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyPreIme
1006c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
10073d25a1f5dbe892330fb2677d8b1030bcbcd60447Kirill Grouchnikov     *
1008c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
1009c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
101002cd0f91059f04136bb3817b41305c2909f4f1d5Alan Viverette    public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) {
1011c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
1012c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // special case for the back key, we do not even try to send it
1013c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // to the drop down list but instead, consume it immediately
1014c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final View anchorView = mDropDownAnchorView;
1015c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
1016b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
1017b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                if (state != null) {
1018b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    state.startTracking(event, this);
1019b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                }
1020c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                return true;
1021c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (event.getAction() == KeyEvent.ACTION_UP) {
1022b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
1023b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                if (state != null) {
1024b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    state.handleUpEvent(event);
1025b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                }
1026c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (event.isTracking() && !event.isCanceled()) {
1027c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    dismiss();
1028c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    return true;
1029c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1030c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1031c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1032c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
1033c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1034c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1035c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
10361955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * Returns an {@link OnTouchListener} that can be added to the source view
10371955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * to implement drag-to-open behavior. Generally, the source view should be
10381955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * the same view that was passed to {@link #setAnchorView}.
10391955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * <p>
10401955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * When the listener is set on a view, touching that view and dragging
10411955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * outside of its bounds will open the popup window. Lifting will select the
10421955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * currently touched list item.
10431955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * <p>
10441955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * Example usage:
10453f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * <pre>
10463f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * ListPopupWindow myPopup = new ListPopupWindow(context);
10471955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * myPopup.setAnchor(myAnchor);
10481955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * OnTouchListener dragListener = myPopup.createDragToOpenListener(myAnchor);
10493f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * myAnchor.setOnTouchListener(dragListener);
10503f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * </pre>
10511955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     *
10521955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * @param src the view on which the resulting listener will be set
10531955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * @return a touch listener that controls drag-to-open behavior
10541955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     */
10551955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    public OnTouchListener createDragToOpenListener(View src) {
10561955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette        return new ForwardingListener(src) {
10571955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette            @Override
1058f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg            public ShowableListMenu getPopup() {
10591955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette                return ListPopupWindow.this;
10601955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette            }
10611955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette        };
10621955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    }
10631955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette
10641955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    /**
1065c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Builds the popup window's content and returns the height the popup
1066c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * should have. Returns -1 when the content already exists.</p>
1067c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
1068c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return the content's height or -1 if content already exists
1069c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
1070c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int buildDropDown() {
1071c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        ViewGroup dropDownView;
1072c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int otherHeights = 0;
1073c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1074c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownList == null) {
1075c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            Context context = mContext;
1076c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1077c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            /**
1078c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * This Runnable exists for the sole purpose of checking if the view layout has got
1079c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * completed and if so call showDropDown to display the drop down. This is used to show
1080c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * the drop down as soon as possible after user opens up the search dialog, without
1081c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * waiting for the normal UI pipeline to do it's job which is slower than this method.
1082c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             */
1083c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mShowDropDownRunnable = new Runnable() {
1084c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void run() {
1085c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // View layout should be all done before displaying the drop down.
1086c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    View view = getAnchorView();
1087c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (view != null && view.getWindowToken() != null) {
1088c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        show();
1089c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
1090c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1091c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            };
1092c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
109331f581c5a64320d9a90ce3fb1a4625f94f4f8021Jun Mukai            mDropDownList = createDropDownListView(context, !mModal);
1094c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownListHighlight != null) {
1095c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mDropDownList.setSelector(mDropDownListHighlight);
1096c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1097c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setAdapter(mAdapter);
1098c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnItemClickListener(mItemClickListener);
1099c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setFocusable(true);
1100c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setFocusableInTouchMode(true);
1101c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1102c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void onItemSelected(AdapterView<?> parent, View view,
1103c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        int position, long id) {
1104c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1105c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (position != -1) {
1106c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        DropDownListView dropDownList = mDropDownList;
1107c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1108c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        if (dropDownList != null) {
1109f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg                            dropDownList.setListSelectionHidden(false);
1110c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        }
1111c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
1112c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1113c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1114c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void onNothingSelected(AdapterView<?> parent) {
1115c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1116c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            });
1117c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnScrollListener(mScrollListener);
1118c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1119c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mItemSelectedListener != null) {
1120c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
1121c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1122c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1123c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dropDownView = mDropDownList;
1124c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1125c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            View hintView = mPromptView;
1126c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (hintView != null) {
1127f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa                // if a hint has been specified, we accomodate more space for it and
1128c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // add a text view in the drop down menu, at the bottom of the list
1129c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout hintContainer = new LinearLayout(context);
1130c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintContainer.setOrientation(LinearLayout.VERTICAL);
1131c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1132c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
1133c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f
1134c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                );
1135c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1136c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                switch (mPromptPosition) {
1137c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                case POSITION_PROMPT_BELOW:
1138c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(dropDownView, hintParams);
1139c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(hintView);
1140c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1141c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1142c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                case POSITION_PROMPT_ABOVE:
1143c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(hintView);
1144c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(dropDownView, hintParams);
1145c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1146c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1147c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                default:
1148c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    Log.e(TAG, "Invalid hint position " + mPromptPosition);
1149c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1150c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1151c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1152ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                // Measure the hint's height to find how much more vertical
1153ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                // space we need to add to the drop down's height.
1154ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                final int widthSize;
1155ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                final int widthMode;
1156ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                if (mDropDownWidth >= 0) {
1157ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                    widthMode = MeasureSpec.AT_MOST;
1158ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                    widthSize = mDropDownWidth;
1159ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                } else {
1160ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                    widthMode = MeasureSpec.UNSPECIFIED;
1161ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                    widthSize = 0;
1162ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                }
1163ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode);
1164ba4332d9cf09b7e342783e39efd41646792a5b06Alan Viverette                final int heightSpec = MeasureSpec.UNSPECIFIED;
1165c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintView.measure(widthSpec, heightSpec);
1166c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1167c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
1168c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin
1169c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        + hintParams.bottomMargin;
1170c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                dropDownView = hintContainer;
1172c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1174c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setContentView(dropDownView);
1175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else {
1176c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final View view = mPromptView;
1177c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (view != null) {
1178c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout.LayoutParams hintParams =
1179c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        (LinearLayout.LayoutParams) view.getLayoutParams();
1180c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                otherHeights = view.getMeasuredHeight() + hintParams.topMargin
1181c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        + hintParams.bottomMargin;
1182c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1183c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1184c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
11858132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        // getMaxAvailableHeight() subtracts the padding, so we put it back
11861e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        // to get the available height for the whole window.
11871e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        final int padding;
11881e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        final Drawable background = mPopup.getBackground();
1189c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (background != null) {
1190c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            background.getPadding(mTempRect);
1191c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            padding = mTempRect.top + mTempRect.bottom;
11928132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell
11931e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette            // If we don't have an explicit vertical offset, determine one from
11941e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette            // the window background so that content will line up.
11958132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            if (!mDropDownVerticalOffsetSet) {
11968132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                mDropDownVerticalOffset = -mTempRect.top;
11978132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            }
11987507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        } else {
11997507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            mTempRect.setEmpty();
12001e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette            padding = 0;
1201c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1202c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
12038132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        // Max height available on the screen for a popup.
12041e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        final boolean ignoreBottomDecorations =
12058132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
12068132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        final int maxHeight = mPopup.getMaxAvailableHeight(
12078132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
1208c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
1209c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return maxHeight + padding;
1210c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1211c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
12127507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        final int childWidthSpec;
12137507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        switch (mDropDownWidth) {
12147507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            case ViewGroup.LayoutParams.WRAP_CONTENT:
12157507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(
12161e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                        mContext.getResources().getDisplayMetrics().widthPixels
12171e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                                - (mTempRect.left + mTempRect.right),
12187507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        MeasureSpec.AT_MOST);
12197507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
12207507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            case ViewGroup.LayoutParams.MATCH_PARENT:
12217507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(
12221e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                        mContext.getResources().getDisplayMetrics().widthPixels
12231e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                                - (mTempRect.left + mTempRect.right),
12247507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        MeasureSpec.EXACTLY);
12257507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
12267507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            default:
12277507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY);
12287507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
12297507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        }
12301e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette
12311e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        // Add padding only if the list has items in it, that way we don't show
12321e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        // the popup if it is not needed.
12337507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        final int listContent = mDropDownList.measureHeightOfChildren(childWidthSpec,
12341e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                0, DropDownListView.NO_POSITION, maxHeight - otherHeights, -1);
12351e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        if (listContent > 0) {
12361e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette            final int listPadding = mDropDownList.getPaddingTop()
12371e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette                    + mDropDownList.getPaddingBottom();
12381e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette            otherHeights += padding + listPadding;
12391e2c2d45090db36b73df105ec37b7b896e5bab3cAlan Viverette        }
1240c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1241c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return listContent + otherHeights;
1242c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1243c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1244c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupDataSetObserver extends DataSetObserver {
1245c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1246c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onChanged() {
1247c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (isShowing()) {
1248c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // Resize the popup to fit new content
1249c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                show();
1250c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1251c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1252c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1253c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1254c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onInvalidated() {
1255c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dismiss();
1256c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1257c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1258c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1259c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class ListSelectorHider implements Runnable {
1260c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void run() {
1261c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            clearListSelection();
1262c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1263c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1264c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1265c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class ResizePopupRunnable implements Runnable {
1266c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void run() {
1267c8bfc68cddc15787943e7db1ba1cfeb26d4f74d3Alan Viverette            if (mDropDownList != null && mDropDownList.isAttachedToWindow()
1268c8bfc68cddc15787943e7db1ba1cfeb26d4f74d3Alan Viverette                    && mDropDownList.getCount() > mDropDownList.getChildCount()
1269c8bfc68cddc15787943e7db1ba1cfeb26d4f74d3Alan Viverette                    && mDropDownList.getChildCount() <= mListItemExpandMaximum) {
1270348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell                mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
1271348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell                show();
1272348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell            }
1273c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1274c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1275c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1276c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupTouchInterceptor implements OnTouchListener {
1277c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean onTouch(View v, MotionEvent event) {
1278c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int action = event.getAction();
1279c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int x = (int) event.getX();
1280c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int y = (int) event.getY();
1281c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1282c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (action == MotionEvent.ACTION_DOWN &&
1283c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup != null && mPopup.isShowing() &&
1284711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunne                    (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) {
1285c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT);
1286c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (action == MotionEvent.ACTION_UP) {
1287c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.removeCallbacks(mResizePopupRunnable);
1288c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1289c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return false;
1290c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1291c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1292c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1293c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupScrollListener implements ListView.OnScrollListener {
1294c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
1295c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int totalItemCount) {
1296c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1297c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1298c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1299c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onScrollStateChanged(AbsListView view, int scrollState) {
1300c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (scrollState == SCROLL_STATE_TOUCH_SCROLL &&
1301c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    !isInputMethodNotNeeded() && mPopup.getContentView() != null) {
1302c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.removeCallbacks(mResizePopupRunnable);
1303c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mResizePopupRunnable.run();
1304c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1305c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1306c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1307c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell}
1308