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
19c05027214f1f4dda67296a072dfc9af9176dc590Alan Viveretteimport android.animation.Animator;
20c05027214f1f4dda67296a072dfc9af9176dc590Alan Viveretteimport android.animation.AnimatorListenerAdapter;
21c05027214f1f4dda67296a072dfc9af9176dc590Alan Viveretteimport android.animation.ObjectAnimator;
22c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.content.Context;
23c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.database.DataSetObserver;
24c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.graphics.Rect;
25c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.graphics.drawable.Drawable;
26c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.os.Handler;
27d3d9f3f1004dfee2649a26cfe8dba948cd364904Fabrice Di Meglioimport android.text.TextUtils;
28c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.util.AttributeSet;
29c05027214f1f4dda67296a072dfc9af9176dc590Alan Viveretteimport android.util.IntProperty;
30c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.util.Log;
3154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powellimport android.view.Gravity;
32c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.KeyEvent;
33c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.MotionEvent;
34c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View;
35c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View.MeasureSpec;
3669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viveretteimport android.view.View.OnAttachStateChangeListener;
37c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellimport android.view.View.OnTouchListener;
38ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viveretteimport android.view.ViewConfiguration;
39711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunneimport android.view.ViewGroup;
40711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunneimport android.view.ViewParent;
41c05027214f1f4dda67296a072dfc9af9176dc590Alan Viveretteimport android.view.animation.AccelerateDecelerateInterpolator;
42c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
435e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viveretteimport com.android.internal.widget.AutoScrollHelper.AbsListViewAutoScroller;
445e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette
451d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglioimport java.util.Locale;
461d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio
47c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell/**
48c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * A ListPopupWindow anchors itself to a host view and displays a
4965d79fbe55c017edd9419ddb71939c8916471390Adam Powell * list of choices.
50c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
51c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * <p>ListPopupWindow contains a number of tricky behaviors surrounding
52c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * positioning, scrolling parents to fit the dropdown, interacting
53c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * sanely with the IME if present, and others.
54c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell *
55c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @see android.widget.AutoCompleteTextView
56c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @see android.widget.Spinner
57c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */
58c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powellpublic class ListPopupWindow {
59c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final String TAG = "ListPopupWindow";
60c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final boolean DEBUG = false;
61c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
62c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
63c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * This value controls the length of time that the user
64c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * must leave a pointer down without scrolling to expand
65c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the autocomplete dropdown list to cover the IME.
66c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
67c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final int EXPAND_LIST_TIMEOUT = 250;
68c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
69c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Context mContext;
70c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private PopupWindow mPopup;
71c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private ListAdapter mAdapter;
72c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private DropDownListView mDropDownList;
73c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
74c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
75c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
76c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownHorizontalOffset;
77c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mDropDownVerticalOffset;
788132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell    private boolean mDropDownVerticalOffsetSet;
79c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
8054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    private int mDropDownGravity = Gravity.NO_GRAVITY;
8154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
82c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mDropDownAlwaysVisible = false;
83c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mForceIgnoreOutsideTouch = false;
84348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    int mListItemExpandMaximum = Integer.MAX_VALUE;
85c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
86c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private View mPromptView;
87c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int mPromptPosition = POSITION_PROMPT_ABOVE;
88c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
89c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private DataSetObserver mObserver;
90c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
91c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private View mDropDownAnchorView;
92c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
93c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Drawable mDropDownListHighlight;
94c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
95c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private AdapterView.OnItemClickListener mItemClickListener;
96c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private AdapterView.OnItemSelectedListener mItemSelectedListener;
97c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
984267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable();
99c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor();
100c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final PopupScrollListener mScrollListener = new PopupScrollListener();
101c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private final ListSelectorHider mHideSelector = new ListSelectorHider();
102c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Runnable mShowDropDownRunnable;
103c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
104c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Handler mHandler = new Handler();
105c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
106c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private Rect mTempRect = new Rect();
107c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
108c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private boolean mModal;
109c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1101d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio    private int mLayoutDirection;
1111d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio
112c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
113c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The provided prompt view should appear above list content.
114c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
115c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptPosition(int)
116c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getPromptPosition()
117c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptView(View)
118c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
119c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int POSITION_PROMPT_ABOVE = 0;
120c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
121c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
122c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The provided prompt view should appear below list content.
123c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
124c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptPosition(int)
125c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getPromptPosition()
126c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setPromptView(View)
127c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
128c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int POSITION_PROMPT_BELOW = 1;
129c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
130c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
131c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Alias for {@link ViewGroup.LayoutParams#MATCH_PARENT}.
132c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup width, the popup will match the width of the anchor view.
133c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup height, the popup will fill available space.
134c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
135c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT;
136c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
137c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
138c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}.
139c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If used to specify a popup width, the popup will use the width of its content.
140c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
141c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
142c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
143c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
144c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
145c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * input method should be based on the focusability of the popup.  That is
146c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if it is focusable than it needs to work with the input method, else
147c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * it doesn't.
148c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
149c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE;
150c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
151c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
152c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
153c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * work with an input method, regardless of whether it is focusable.  This
154c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * means that it will always be displayed so that the user can also operate
155c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the input method while it is shown.
156c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
157c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED;
158c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
159c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
160c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
161c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * work with an input method, regardless of whether it is focusable.  This
162c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * means that it will always be displayed to use as much space on the
163c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * screen as needed, regardless of whether this covers the input method.
164c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
165c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int INPUT_METHOD_NOT_NEEDED = PopupWindow.INPUT_METHOD_NOT_NEEDED;
166c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
167c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
168c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
169c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
170c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
172c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public ListPopupWindow(Context context) {
174c2238d006237ebf1296074d80fb4f4a2741ef880Daniel Lehmann        this(context, null, com.android.internal.R.attr.listPopupWindowStyle, 0);
175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
176c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
177c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
178c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
179c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
180c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
181c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
182c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
183c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
184c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public ListPopupWindow(Context context, AttributeSet attrs) {
1850b2d306e7000f4c0c6ad4e00d494bb401d8a9fc2Adam Powell        this(context, attrs, com.android.internal.R.attr.listPopupWindowStyle, 0);
186c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
187c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
188c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
189c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
190c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
191c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
192c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
193c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
194c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleAttr Default style attribute to use for popup content.
195c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
196c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
197c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        this(context, attrs, defStyleAttr, 0);
198c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
199c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
200c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
201c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Create a new, empty popup window capable of displaying items from a ListAdapter.
202c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}.
203c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
204c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param context Context used for contained views.
205c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param attrs Attributes from inflating parent views used to style the popup.
206c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleAttr Style attribute to read for default styling of popup content.
207c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param defStyleRes Style resource ID to use for default styling of popup content.
208c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
209c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
210c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mContext = context;
211c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup = new PopupWindow(context, attrs, defStyleAttr, defStyleRes);
2126f5e934b96c400f610b1c5ad228cc60cab5d443fAdam Powell        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
2131d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio        // Set the default layout direction to match the default locale one
2141d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio        final Locale locale = mContext.getResources().getConfiguration().locale;
215d3d9f3f1004dfee2649a26cfe8dba948cd364904Fabrice Di Meglio        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
216c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
217c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
218c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
219c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the adapter that provides the data and the views to represent the data
220c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * in this popup window.
221c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
222c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param adapter The adapter to use to create this window's content.
223c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
224c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setAdapter(ListAdapter adapter) {
225c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mObserver == null) {
226c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mObserver = new PopupDataSetObserver();
227c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else if (mAdapter != null) {
22899969da3772d9a0f5079672847ca4f2ad819c1bbAdam Powell            mAdapter.unregisterDataSetObserver(mObserver);
229c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
230c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mAdapter = adapter;
231c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mAdapter != null) {
232c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            adapter.registerDataSetObserver(mObserver);
233c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
234c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
235c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownList != null) {
236c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setAdapter(mAdapter);
237c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
238c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
239c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
240c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
241c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set where the optional prompt view should appear. The default is
242c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #POSITION_PROMPT_ABOVE}.
243c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
244c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position A position constant declaring where the prompt should be displayed.
245c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
246c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_ABOVE
247c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_BELOW
248c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
249c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setPromptPosition(int position) {
250c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPromptPosition = position;
251c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
252c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
253c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
254c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Where the optional prompt view should appear.
255c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
256c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_ABOVE
257c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #POSITION_PROMPT_BELOW
258c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
259c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getPromptPosition() {
260c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPromptPosition;
261c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
262c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
263c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
264c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set whether this window should be modal when shown.
265c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
266c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>If a popup window is modal, it will receive all touch and key input.
267c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * If the user touches outside the popup window's content area the popup window
268c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * will be dismissed.
269c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
270c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param modal {@code true} if the popup window should be modal, {@code false} otherwise.
271c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
272c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setModal(boolean modal) {
273c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mModal = true;
274c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setFocusable(modal);
275c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
276c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
277c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
278c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns whether the popup window will be modal when shown.
279c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
280c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if the popup window will be modal, {@code false} otherwise.
281c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
282c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isModal() {
283c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mModal;
284c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
285c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
286c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
287c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
288c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we
289c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * ignore outside touch even when the drop down is not set to always visible.
290c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
291c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Used only by AutoCompleteTextView to handle some internal special cases.
292c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
293c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
294c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
295c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
296c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
297c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
298c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets whether the drop-down should remain visible under certain conditions.
299c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
300c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless
301c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * of the size or content of the list.  {@link #getBackground()} will fill any space
302c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * that is not used by the list.
303c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
304c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
305c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
306c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Only used by AutoCompleteTextView under special conditions.
307c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
308c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
309c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownAlwaysVisible = dropDownAlwaysVisible;
310c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
311c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
312c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
313c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Whether the drop-down is visible under special conditions.
314c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
315c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @hide Only used by AutoCompleteTextView under special conditions.
316c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
317c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isDropDownAlwaysVisible() {
318c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownAlwaysVisible;
319c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
320c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
321c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
322c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the operating mode for the soft input area.
323c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
324c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param mode The desired mode, see
325c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *        {@link android.view.WindowManager.LayoutParams#softInputMode}
326c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *        for the full list
327c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
328c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see android.view.WindowManager.LayoutParams#softInputMode
329c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getSoftInputMode()
330c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
331c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setSoftInputMode(int mode) {
332c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setSoftInputMode(mode);
333c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
334c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
335c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
336c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the current value in {@link #setSoftInputMode(int)}.
337c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
338c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setSoftInputMode(int)
339c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see android.view.WindowManager.LayoutParams#softInputMode
340c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
341c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getSoftInputMode() {
342c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getSoftInputMode();
343c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
344c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
345c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
346c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a drawable to use as the list item selector.
347c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
348c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param selector List selector drawable to use in the popup.
349c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
350c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setListSelector(Drawable selector) {
351c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownListHighlight = selector;
352c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
353c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
354c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
355c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The background drawable for the popup window.
356c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
357c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public Drawable getBackground() {
358c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getBackground();
359c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
360c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
361c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
362c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a drawable to be the background for the popup window.
363c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
364c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param d A drawable to set as the background.
365c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
366c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setBackgroundDrawable(Drawable d) {
367c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setBackgroundDrawable(d);
368c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
369c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
370c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
371c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set an animation style to use when the popup window is shown or dismissed.
372c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
373c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param animationStyle Animation style to use.
374c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
375c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setAnimationStyle(int animationStyle) {
376c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setAnimationStyle(animationStyle);
377c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
378c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
379c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
380c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the animation style that will be used when the popup window is
381c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * shown or dismissed.
382c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
383c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return Animation style that will be used.
384c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
385c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getAnimationStyle() {
386c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getAnimationStyle();
387c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
388c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
389c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
390c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Returns the view that will be used to anchor this popup.
391c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
392c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The popup's anchor view
393c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
394c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public View getAnchorView() {
395c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownAnchorView;
396c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
397c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
398c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
399c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the popup's anchor view. This popup will always be positioned relative to
400c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the anchor view when shown.
401c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
402c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param anchor The view to use as an anchor.
403c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
404c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setAnchorView(View anchor) {
405c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownAnchorView = anchor;
406c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
407c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
408c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
409c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The horizontal offset of the popup from its anchor in pixels.
410c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
411c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getHorizontalOffset() {
412c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownHorizontalOffset;
413c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
414c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
415c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
416c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the horizontal offset of this popup from its anchor view in pixels.
417c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
418a984b38df5cfe6db0ba792bf2a6221f6b6072448Adam Powell     * @param offset The horizontal offset of the popup from its anchor.
419c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
420c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setHorizontalOffset(int offset) {
421c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownHorizontalOffset = offset;
422c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
423c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
424c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
425c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The vertical offset of the popup from its anchor in pixels.
426c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
427c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getVerticalOffset() {
4288132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        if (!mDropDownVerticalOffsetSet) {
4298132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            return 0;
4308132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        }
431c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownVerticalOffset;
432c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
433c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
434c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
435c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the vertical offset of this popup from its anchor view in pixels.
436c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
437a984b38df5cfe6db0ba792bf2a6221f6b6072448Adam Powell     * @param offset The vertical offset of the popup from its anchor.
438c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
439c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setVerticalOffset(int offset) {
440c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownVerticalOffset = offset;
4418132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        mDropDownVerticalOffsetSet = true;
442c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
443c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
444c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
44554c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * Set the gravity of the dropdown list. This is commonly used to
44654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * set gravity to START or END for alignment with the anchor.
44754c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     *
44854c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     * @param gravity Gravity value to use
44954c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell     */
45054c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    public void setDropDownGravity(int gravity) {
45154c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell        mDropDownGravity = gravity;
45254c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    }
45354c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell
45454c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell    /**
455c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The width of the popup window in pixels.
456c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
457c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getWidth() {
458c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownWidth;
459c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
460c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
461c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
462c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the width of the popup window in pixels. Can also be {@link #MATCH_PARENT}
463c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * or {@link #WRAP_CONTENT}.
464c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
465c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param width Width of the popup window.
466c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
467c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setWidth(int width) {
468c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownWidth = width;
469c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
470c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
471c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
4724267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * Sets the width of the popup window by the size of its content. The final width may be
4734267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * larger to accommodate styled window dressing.
4744267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     *
4754267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     * @param width Desired width of content in pixels.
4764267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell     */
4774267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    public void setContentWidth(int width) {
4784267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        Drawable popupBackground = mPopup.getBackground();
4794267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        if (popupBackground != null) {
480a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            popupBackground.getPadding(mTempRect);
481a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            mDropDownWidth = mTempRect.left + mTempRect.right + width;
48262e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell        } else {
48362e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell            setWidth(width);
4844267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell        }
4854267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    }
4864267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell
4874267534d1c42af847ed0cefd1c88c99f66b36571Adam Powell    /**
488c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The height of the popup window in pixels.
489c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
490c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getHeight() {
491c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownHeight;
492c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
493c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
494c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
495c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}.
496c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
497c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param height Height of the popup window.
498c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
499c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setHeight(int height) {
500c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownHeight = height;
501c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
502c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
503c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
504c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a listener to receive events when a list item is clicked.
505c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
506c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param clickListener Listener to register
507c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
508c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
509c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
510c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) {
511c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mItemClickListener = clickListener;
512c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
513c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
514c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
515c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Sets a listener to receive events when a list item is selected.
516c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
517c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param selectedListener Listener to register.
518c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
519c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
520c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
521c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener selectedListener) {
522c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mItemSelectedListener = selectedListener;
523c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
524c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
525c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
526c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set a view to act as a user prompt for this popup window. Where the prompt view will appear
527c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * is controlled by {@link #setPromptPosition(int)}.
528c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
529c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param prompt View to use as an informational prompt.
530c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
531c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setPromptView(View prompt) {
532c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        boolean showing = isShowing();
533c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (showing) {
534c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            removePromptView();
535c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
536c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPromptView = prompt;
537c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (showing) {
538c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            show();
539c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
540c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
541c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
542c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
543c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Post a {@link #show()} call to the UI thread.
544c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
545c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void postShow() {
546c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mHandler.post(mShowDropDownRunnable);
547c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
548c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
549c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
550c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Show the popup list. If the list is already showing, this method
551c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * will recalculate the popup's size and position.
552c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
553c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void show() {
554c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int height = buildDropDown();
555c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
556c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int widthSpec = 0;
557c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int heightSpec = 0;
558c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
559c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        boolean noInputMethod = isInputMethodNotNeeded();
560348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mPopup.setAllowScrollingAnchorParent(!noInputMethod);
561c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
562c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mPopup.isShowing()) {
563c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
564c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // The call to PopupWindow's update method below can accept -1 for any
565c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // value you do not want to update.
566c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = -1;
567c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
568c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = getAnchorView().getWidth();
569c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
570c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = mDropDownWidth;
571c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
572c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
573c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
574c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // The call to PopupWindow's update method below can accept -1 for any
575c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // value you do not want to update.
576c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT;
577c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (noInputMethod) {
578c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setWindowLayoutMode(
579c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
580c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                                    ViewGroup.LayoutParams.MATCH_PARENT : 0, 0);
581c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
582c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setWindowLayoutMode(
583c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ?
584c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                                    ViewGroup.LayoutParams.MATCH_PARENT : 0,
585c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            ViewGroup.LayoutParams.MATCH_PARENT);
586c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
587c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
588c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = height;
589c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
590c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = mDropDownHeight;
591c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
592c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
593c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
594c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
595c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
596c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mDropDownVerticalOffset, widthSpec, heightSpec);
597c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else {
598c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
599c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                widthSpec = ViewGroup.LayoutParams.MATCH_PARENT;
600c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
601c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
602c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setWidth(getAnchorView().getWidth());
603c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
604c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setWidth(mDropDownWidth);
605c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
606c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
607c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
608c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
609c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                heightSpec = ViewGroup.LayoutParams.MATCH_PARENT;
610c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else {
611c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
612c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setHeight(height);
613c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
614c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setHeight(mDropDownHeight);
615c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
616c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
617c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
618c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setWindowLayoutMode(widthSpec, heightSpec);
61956c2d337e02a275397fc9d0460dca90977f199acAdam Powell            mPopup.setClipToScreenEnabled(true);
620c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
621c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // use outside touchable to dismiss drop down when touching outside of it, so
622c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // only set this if the dropdown is not always visible
623c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
624c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setTouchInterceptor(mTouchInterceptor);
625c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.showAsDropDown(getAnchorView(),
62654c94dea8a26e66fa59a31fd9170ca221052d3aaAdam Powell                    mDropDownHorizontalOffset, mDropDownVerticalOffset, mDropDownGravity);
627c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setSelection(ListView.INVALID_POSITION);
628c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
629c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (!mModal || mDropDownList.isInTouchMode()) {
630c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                clearListSelection();
631c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
632c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (!mModal) {
633c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.post(mHideSelector);
634c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
635c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
636c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
637c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
638c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
639c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Dismiss the popup window.
640c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
641c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void dismiss() {
642c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.dismiss();
643c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        removePromptView();
644c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setContentView(null);
645c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mDropDownList = null;
646ca51e8788a58f2af3525b7214a675f2d0233e5daAdam Powell        mHandler.removeCallbacks(mResizePopupRunnable);
647c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
648c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
6496c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    /**
6506c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     * Set a listener to receive a callback when the popup is dismissed.
6516c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     *
6526c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     * @param listener Listener that will be notified when the popup is dismissed.
6536c6f575423d6718c3ff322224c1520901ce881e1Adam Powell     */
6546c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
6556c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        mPopup.setOnDismissListener(listener);
6566c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    }
6576c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
658c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private void removePromptView() {
659c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mPromptView != null) {
660c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final ViewParent parent = mPromptView.getParent();
661c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (parent instanceof ViewGroup) {
662c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final ViewGroup group = (ViewGroup) parent;
663c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                group.removeView(mPromptView);
664c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
665c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
666c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
667c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
668c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
669c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Control how the popup operates with an input method: one of
670c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED},
671c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * or {@link #INPUT_METHOD_NOT_NEEDED}.
672c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
673c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>If the popup is showing, calling this method will take effect only
674c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * the next time the popup is shown or through a manual call to the {@link #show()}
675c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * method.</p>
676c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
677c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #getInputMethodMode()
678c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #show()
679c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
680c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setInputMethodMode(int mode) {
681c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setInputMethodMode(mode);
682c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
683c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
684c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
685c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Return the current value in {@link #setInputMethodMode(int)}.
686c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
687c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setInputMethodMode(int)
688c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
689c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getInputMethodMode() {
690c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getInputMethodMode();
691c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
692c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
693c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
694c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Set the selected position of the list.
695c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
696c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
697c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position List position to set as selected.
698c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
699c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setSelection(int position) {
700c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        DropDownListView list = mDropDownList;
701c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing() && list != null) {
702c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.mListSelectionHidden = false;
703c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.setSelection(position);
704c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) {
705c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                list.setItemChecked(position, true);
706c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
707c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
708c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
709c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
710c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
711c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Clear any current list selection.
712c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
713c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
714c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void clearListSelection() {
715c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        final DropDownListView list = mDropDownList;
716c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (list != null) {
717c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // WARNING: Please read the comment where mListSelectionHidden is declared
718c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.mListSelectionHidden = true;
719c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.hideSelector();
720c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            list.requestLayout();
721c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
722c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
723c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
724c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
725c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if the popup is currently showing, {@code false} otherwise.
726c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
727c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isShowing() {
728c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.isShowing();
729c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
730c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
731c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
732c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return {@code true} if this popup is configured to assume the user does not need
733c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * to interact with the IME while it is showing, {@code false} otherwise.
734c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
735c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean isInputMethodNotNeeded() {
736c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getInputMethodMode() == INPUT_METHOD_NOT_NEEDED;
737c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
738c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
739c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
740c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Perform an item click operation on the specified list adapter position.
741c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
742c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param position Adapter position for performing the click
743c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the click action could be performed, false if not.
744c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *         (e.g. if the popup was not showing, this method would return false.)
745c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
746c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean performItemClick(int position) {
747c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing()) {
748c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mItemClickListener != null) {
749c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final DropDownListView list = mDropDownList;
750c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final View child = list.getChildAt(position - list.getFirstVisiblePosition());
751cdee446075811e871fc2af295377bd99c100d16dAdam Powell                final ListAdapter adapter = list.getAdapter();
752cdee446075811e871fc2af295377bd99c100d16dAdam Powell                mItemClickListener.onItemClick(list, child, position, adapter.getItemId(position));
753c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
754c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return true;
755c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
756c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
757c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
758c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
759c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
760c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The currently selected item or null if the popup is not showing.
761c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
762c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public Object getSelectedItem() {
763c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
764c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return null;
765c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
766c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItem();
767c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
768c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
769c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
770c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The position of the currently selected item or {@link ListView#INVALID_POSITION}
771c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if {@link #isShowing()} == {@code false}.
772c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
773c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedItemPosition()
774c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
775c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public int getSelectedItemPosition() {
776c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
777c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return ListView.INVALID_POSITION;
778c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
779c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItemPosition();
780c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
781c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
782c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
783c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID}
784c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * if {@link #isShowing()} == {@code false}.
785c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
786c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedItemId()
787c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
788c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public long getSelectedItemId() {
789c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
790c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return ListView.INVALID_ROW_ID;
791c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
792c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedItemId();
793c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
794c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
795c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
796c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The View for the currently selected item or null if
797c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * {@link #isShowing()} == {@code false}.
798c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
799c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see ListView#getSelectedView()
800c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
801c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public View getSelectedView() {
802c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (!isShowing()) {
803c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return null;
804c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
805c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList.getSelectedView();
806c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
807c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
808c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
809c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return The {@link ListView} displayed within the popup window.
810c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Only valid when {@link #isShowing()} == {@code true}.
811c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
812c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public ListView getListView() {
813c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mDropDownList;
814c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
815c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
816c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
817348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * The maximum number of list items that can be visible and still have
818348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * the list expand when touched.
819348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     *
820348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     * @param max Max number of items that can be visible and still allow the list to expand.
821348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell     */
822348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    void setListItemExpandMax(int max) {
823348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell        mListItemExpandMaximum = max;
824348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    }
825348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell
826348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell    /**
8278d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown     * Filter key down events. By forwarding key down events to this function,
828c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * views using non-modal ListPopupWindow can have it handle key selection of items.
829c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
830c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyDown
831c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyDown
832c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
833c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
834c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
835c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
836c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean onKeyDown(int keyCode, KeyEvent event) {
837c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        // when the drop down is shown, we drive it directly
838c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing()) {
839c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // the key events are forwarded to the list in the drop down view
840c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // note that ListView handles space but we don't want that to happen
841c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // also if selection is not currently in the drop down, then don't
842c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // let center or enter presses go there since that would cause it
843c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // to select one of its items
844c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (keyCode != KeyEvent.KEYCODE_SPACE
845c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    && (mDropDownList.getSelectedItemPosition() >= 0
84624d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                            || !KeyEvent.isConfirmKey(keyCode))) {
847c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int curIndex = mDropDownList.getSelectedItemPosition();
848c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                boolean consumed;
849c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
850c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final boolean below = !mPopup.isAboveAnchor();
851c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
852c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                final ListAdapter adapter = mAdapter;
853c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
854c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                boolean allEnabled;
855c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int firstItem = Integer.MAX_VALUE;
856c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int lastItem = Integer.MIN_VALUE;
857c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
858c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (adapter != null) {
859c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    allEnabled = adapter.areAllItemsEnabled();
860c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    firstItem = allEnabled ? 0 :
861c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownList.lookForSelectablePosition(0, true);
862c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    lastItem = allEnabled ? adapter.getCount() - 1 :
863c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
864c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
865c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
866c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
867c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
868c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // When the selection is at the top, we block the key
869c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // event to prevent focus from moving.
870c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    clearListSelection();
871c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
872c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    show();
873c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    return true;
874c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
875c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // WARNING: Please read the comment where mListSelectionHidden
876c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    //          is declared
877c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mDropDownList.mListSelectionHidden = false;
878c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
879c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
880c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                consumed = mDropDownList.onKeyDown(keyCode, event);
881c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed);
882c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
883c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (consumed) {
884c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // If it handled the key event, then the user is
885c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // navigating in the list, so we should put it in front.
886c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
887c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // Here's a little trick we need to do to make sure that
888c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // the list view is actually showing its focus indicator,
889c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // by ensuring it has focus and getting its window out
890c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // of touch mode.
891c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mDropDownList.requestFocusFromTouch();
892c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    show();
893c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
894c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    switch (keyCode) {
895c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // avoid passing the focus from the text view to the
896c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // next component
897c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_ENTER:
898c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_CENTER:
899c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_DOWN:
900c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        case KeyEvent.KEYCODE_DPAD_UP:
901c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            return true;
902c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
903c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                } else {
904c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
905c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // when the selection is at the bottom, we block the
906c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        // event to avoid going to the next focusable widget
907c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        if (curIndex == lastItem) {
908c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            return true;
909c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        }
910c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP &&
911c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            curIndex == firstItem) {
912c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        return true;
913c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
914c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
915c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
916c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
917c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
918c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
919c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
920c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
921c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
922c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Filter key down events. By forwarding key up events to this function,
923c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * views using non-modal ListPopupWindow can have it handle key selection of items.
924c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
925c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyUp
926c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyUp
927c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
928c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
929c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
930c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
931c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean onKeyUp(int keyCode, KeyEvent event) {
932c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
933c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            boolean consumed = mDropDownList.onKeyUp(keyCode, event);
93424d36f592224d1316165f579bb0937df0bf42f7cMichael Wright            if (consumed && KeyEvent.isConfirmKey(keyCode)) {
93524d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                // if the list accepts the key events and the key event was a click, the text view
93624d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                // gets the selected item from the drop down as its content
93724d36f592224d1316165f579bb0937df0bf42f7cMichael Wright                dismiss();
938c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
939c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return consumed;
940c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
941c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
942c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
943c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
944c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
945c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Filter pre-IME key events. By forwarding {@link View#onKeyPreIme(int, KeyEvent)}
946c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * events to this function, views using ListPopupWindow can have it dismiss the popup
947c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * when the back key is pressed.
948c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
949c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param keyCode keyCode param passed to the host view's onKeyPreIme
950c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @param event event param passed to the host view's onKeyPreIme
951c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return true if the event was handled, false if it was ignored.
952c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
953c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @see #setModal(boolean)
954c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
955c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
956c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) {
957c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // special case for the back key, we do not even try to send it
958c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // to the drop down list but instead, consume it immediately
959c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final View anchorView = mDropDownAnchorView;
960c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
961b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
962b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                if (state != null) {
963b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    state.startTracking(event, this);
964b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                }
965c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                return true;
966c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (event.getAction() == KeyEvent.ACTION_UP) {
967b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState();
968b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                if (state != null) {
969b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                    state.handleUpEvent(event);
970b3ea92235c9ccc1ff295839a8f324dcd1c83dd6fJeff Brown                }
971c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                if (event.isTracking() && !event.isCanceled()) {
972c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    dismiss();
973c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    return true;
974c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
975c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
976c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
977c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return false;
978c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
979c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
980c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
9811955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * Returns an {@link OnTouchListener} that can be added to the source view
9821955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * to implement drag-to-open behavior. Generally, the source view should be
9831955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * the same view that was passed to {@link #setAnchorView}.
9841955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * <p>
9851955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * When the listener is set on a view, touching that view and dragging
9861955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * outside of its bounds will open the popup window. Lifting will select the
9871955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * currently touched list item.
9881955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * <p>
9891955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * Example usage:
9903f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * <pre>
9913f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * ListPopupWindow myPopup = new ListPopupWindow(context);
9921955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * myPopup.setAnchor(myAnchor);
9931955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * OnTouchListener dragListener = myPopup.createDragToOpenListener(myAnchor);
9943f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * myAnchor.setOnTouchListener(dragListener);
9953f9832d3c7b30bf4dc8ed9e5123b02daca96c878Alan Viverette     * </pre>
9961955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     *
9971955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * @param src the view on which the resulting listener will be set
9981955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     * @return a touch listener that controls drag-to-open behavior
9991955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette     */
10001955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    public OnTouchListener createDragToOpenListener(View src) {
10011955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette        return new ForwardingListener(src) {
10021955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette            @Override
10031955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette            public ListPopupWindow getPopup() {
10041955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette                return ListPopupWindow.this;
10051955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette            }
10061955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette        };
10071955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    }
10081955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette
10091955a5b531f03dec90f285b590ef62e3d632783cAlan Viverette    /**
1010c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Builds the popup window's content and returns the height the popup
1011c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * should have. Returns -1 when the content already exists.</p>
1012c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     *
1013c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * @return the content's height or -1 if content already exists
1014c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
1015c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private int buildDropDown() {
1016c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        ViewGroup dropDownView;
1017c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int otherHeights = 0;
1018c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1019c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownList == null) {
1020c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            Context context = mContext;
1021c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1022c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            /**
1023c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * This Runnable exists for the sole purpose of checking if the view layout has got
1024c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * completed and if so call showDropDown to display the drop down. This is used to show
1025c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * the drop down as soon as possible after user opens up the search dialog, without
1026c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             * waiting for the normal UI pipeline to do it's job which is slower than this method.
1027c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell             */
1028c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mShowDropDownRunnable = new Runnable() {
1029c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void run() {
1030c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    // View layout should be all done before displaying the drop down.
1031c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    View view = getAnchorView();
1032c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (view != null && view.getWindowToken() != null) {
1033c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        show();
1034c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
1035c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1036c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            };
1037c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1038c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList = new DropDownListView(context, !mModal);
1039c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mDropDownListHighlight != null) {
1040c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mDropDownList.setSelector(mDropDownListHighlight);
1041c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1042c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setAdapter(mAdapter);
1043c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnItemClickListener(mItemClickListener);
1044c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setFocusable(true);
1045c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setFocusableInTouchMode(true);
1046c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
1047c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void onItemSelected(AdapterView<?> parent, View view,
1048c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        int position, long id) {
1049c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1050c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    if (position != -1) {
1051c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        DropDownListView dropDownList = mDropDownList;
1052c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1053c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        if (dropDownList != null) {
1054c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                            dropDownList.mListSelectionHidden = false;
1055c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        }
1056c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    }
1057c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1058c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1059c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void onNothingSelected(AdapterView<?> parent) {
1060c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1061c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            });
1062c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mDropDownList.setOnScrollListener(mScrollListener);
1063c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1064c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mItemSelectedListener != null) {
1065c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
1066c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1067c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1068c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dropDownView = mDropDownList;
1069c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1070c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            View hintView = mPromptView;
1071c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (hintView != null) {
1072f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa                // if a hint has been specified, we accomodate more space for it and
1073c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // add a text view in the drop down menu, at the bottom of the list
1074c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout hintContainer = new LinearLayout(context);
1075c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintContainer.setOrientation(LinearLayout.VERTICAL);
1076c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1077c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
1078c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f
1079c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                );
1080c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1081c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                switch (mPromptPosition) {
1082c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                case POSITION_PROMPT_BELOW:
1083c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(dropDownView, hintParams);
1084c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(hintView);
1085c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1086c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1087c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                case POSITION_PROMPT_ABOVE:
1088c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(hintView);
1089c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    hintContainer.addView(dropDownView, hintParams);
1090c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1091c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1092c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                default:
1093c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    Log.e(TAG, "Invalid hint position " + mPromptPosition);
1094c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    break;
1095c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
1096c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1097c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // measure the hint's height to find how much more vertical space
1098c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // we need to add to the drop down's height
1099c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int widthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.AT_MOST);
1100c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int heightSpec = MeasureSpec.UNSPECIFIED;
1101c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintView.measure(widthSpec, heightSpec);
1102c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1103c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
1104c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin
1105c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        + hintParams.bottomMargin;
1106c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1107c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                dropDownView = hintContainer;
1108c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1109c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1110c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.setContentView(dropDownView);
1111c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        } else {
1112c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dropDownView = (ViewGroup) mPopup.getContentView();
1113c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final View view = mPromptView;
1114c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (view != null) {
1115c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                LinearLayout.LayoutParams hintParams =
1116c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        (LinearLayout.LayoutParams) view.getLayoutParams();
1117c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                otherHeights = view.getMeasuredHeight() + hintParams.topMargin
1118c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                        + hintParams.bottomMargin;
1119c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1120c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1121c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
11228132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        // getMaxAvailableHeight() subtracts the padding, so we put it back
1123c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        // to get the available height for the whole window
1124c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        int padding = 0;
1125c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        Drawable background = mPopup.getBackground();
1126c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (background != null) {
1127c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            background.getPadding(mTempRect);
1128c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            padding = mTempRect.top + mTempRect.bottom;
11298132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell
11308132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            // If we don't have an explicit vertical offset, determine one from the window
11318132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            // background so that content will line up.
11328132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            if (!mDropDownVerticalOffsetSet) {
11338132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                mDropDownVerticalOffset = -mTempRect.top;
11348132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            }
11357507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        } else {
11367507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            mTempRect.setEmpty();
1137c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1138c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
11398132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        // Max height available on the screen for a popup.
11408132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        boolean ignoreBottomDecorations =
11418132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
11428132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell        final int maxHeight = mPopup.getMaxAvailableHeight(
11438132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
11448132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell
1145c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) {
1146c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return maxHeight + padding;
1147c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1148c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
11497507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        final int childWidthSpec;
11507507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        switch (mDropDownWidth) {
11517507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            case ViewGroup.LayoutParams.WRAP_CONTENT:
11527507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(
11537507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        mContext.getResources().getDisplayMetrics().widthPixels -
11547507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        (mTempRect.left + mTempRect.right),
11557507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        MeasureSpec.AT_MOST);
11567507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
11577507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            case ViewGroup.LayoutParams.MATCH_PARENT:
11587507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(
11597507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        mContext.getResources().getDisplayMetrics().widthPixels -
11607507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        (mTempRect.left + mTempRect.right),
11617507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                        MeasureSpec.EXACTLY);
11627507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
11637507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell            default:
11647507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY);
11657507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell                break;
11667507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        }
11677507d3d31cb3d0ca190efc9d6b7ead5d6336f8d6Adam Powell        final int listContent = mDropDownList.measureHeightOfChildren(childWidthSpec,
1168a7845ed44a3722e7d96ca9b677be213da7e8c8feAdam Powell                0, ListView.NO_POSITION, maxHeight - otherHeights, -1);
1169c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        // add padding only if the list has items in it, that way we don't show
1170c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        // the popup if it is not needed
1171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        if (listContent > 0) otherHeights += padding;
1172c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return listContent + otherHeights;
1174c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
11761d3d7da331a3e9dc783819ab6fe29ea21c873f1eFabrice Di Meglio    /**
1177ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette     * Abstract class that forwards touch events to a {@link ListPopupWindow}.
1178ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette     *
1179ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette     * @hide
1180ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette     */
118169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette    public static abstract class ForwardingListener
118269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            implements View.OnTouchListener, View.OnAttachStateChangeListener {
1183ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /** Scaled touch slop, used for detecting movement outside bounds. */
1184ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        private final float mScaledTouchSlop;
1185ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
118669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        /** Timeout before disallowing intercept on the source's parent. */
118769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private final int mTapTimeout;
118869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
118969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        /** Source view from which events are forwarded. */
119069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private final View mSrc;
119169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
119269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        /** Runnable used to prevent conflicts with scrolling parents. */
119369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private Runnable mDisallowIntercept;
119469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
1195ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /** Whether this listener is currently forwarding touch events. */
1196ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        private boolean mForwarding;
1197ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1198ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /** The id of the first pointer down in the current event stream. */
1199ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        private int mActivePointerId;
1200ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
120169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        public ForwardingListener(View src) {
120269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            mSrc = src;
120369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            mScaledTouchSlop = ViewConfiguration.get(src.getContext()).getScaledTouchSlop();
120469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            mTapTimeout = ViewConfiguration.getTapTimeout();
120569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
120669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            src.addOnAttachStateChangeListener(this);
1207ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
1208ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1209ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /**
1210ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Returns the popup to which this listener is forwarding events.
1211ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * <p>
1212ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Override this to return the correct popup. If the popup is displayed
1213ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * asynchronously, you may also need to override
1214ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * {@link #onForwardingStopped} to prevent premature cancelation of
1215ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * forwarding.
1216ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         *
1217ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @return the popup to which this listener is forwarding events
1218ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         */
1219ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        public abstract ListPopupWindow getPopup();
1220ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1221ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        @Override
1222ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        public boolean onTouch(View v, MotionEvent event) {
1223ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final boolean wasForwarding = mForwarding;
1224ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final boolean forwarding;
1225ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (wasForwarding) {
122669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                forwarding = onTouchForwarded(event) || !onForwardingStopped();
1227ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            } else {
122869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                forwarding = onTouchObserved(event) && onForwardingStarted();
1229ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1230ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1231ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            mForwarding = forwarding;
1232ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            return forwarding || wasForwarding;
1233ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
1234ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
123569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        @Override
123669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        public void onViewAttachedToWindow(View v) {
123769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        }
123869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
123969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        @Override
124069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        public void onViewDetachedFromWindow(View v) {
124169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            mForwarding = false;
124269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            mActivePointerId = MotionEvent.INVALID_POINTER_ID;
124369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
124469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            if (mDisallowIntercept != null) {
124569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                mSrc.removeCallbacks(mDisallowIntercept);
124669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            }
124769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        }
124869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
1249ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /**
1250ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Called when forwarding would like to start.
1251ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * <p>
1252ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * By default, this will show the popup returned by {@link #getPopup()}.
1253ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * It may be overridden to perform another action, like clicking the
1254ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * source view or preparing the popup before showing it.
1255ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         *
1256ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @return true to start forwarding, false otherwise
1257ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         */
125869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        protected boolean onForwardingStarted() {
1259ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final ListPopupWindow popup = getPopup();
1260ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (popup != null && !popup.isShowing()) {
1261ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                popup.show();
1262ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1263ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            return true;
1264ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
1265ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1266ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /**
1267ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Called when forwarding would like to stop.
1268ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * <p>
1269ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * By default, this will dismiss the popup returned by
1270ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * {@link #getPopup()}. It may be overridden to perform some other
1271ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * action.
1272ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         *
1273ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @return true to stop forwarding, false otherwise
1274ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         */
127569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        protected boolean onForwardingStopped() {
1276ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final ListPopupWindow popup = getPopup();
1277ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (popup != null && popup.isShowing()) {
1278ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                popup.dismiss();
1279ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1280ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            return true;
1281ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
1282ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1283ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /**
1284ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Observes motion events and determines when to start forwarding.
1285ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         *
1286ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @param srcEvent motion event in source view coordinates
1287ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @return true to start forwarding motion events, false otherwise
1288ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         */
128969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private boolean onTouchObserved(MotionEvent srcEvent) {
129069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            final View src = mSrc;
1291ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (!src.isEnabled()) {
1292ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                return false;
1293ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1294ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1295ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final int actionMasked = srcEvent.getActionMasked();
129669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            switch (actionMasked) {
129769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                case MotionEvent.ACTION_DOWN:
129869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    mActivePointerId = srcEvent.getPointerId(0);
129969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    if (mDisallowIntercept == null) {
130069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        mDisallowIntercept = new DisallowIntercept();
130169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    }
130269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    src.postDelayed(mDisallowIntercept, mTapTimeout);
130369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    break;
130469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                case MotionEvent.ACTION_MOVE:
130569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    final int activePointerIndex = srcEvent.findPointerIndex(mActivePointerId);
130669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    if (activePointerIndex >= 0) {
130769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        final float x = srcEvent.getX(activePointerIndex);
130869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        final float y = srcEvent.getY(activePointerIndex);
130969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        if (!src.pointInView(x, y, mScaledTouchSlop)) {
131069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                            // The pointer has moved outside of the view.
131169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                            if (mDisallowIntercept != null) {
131269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                                src.removeCallbacks(mDisallowIntercept);
131369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                            }
131469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                            src.getParent().requestDisallowInterceptTouchEvent(true);
131569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                            return true;
131669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        }
131769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    }
131869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    break;
131969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                case MotionEvent.ACTION_CANCEL:
132069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                case MotionEvent.ACTION_UP:
132169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    if (mDisallowIntercept != null) {
132269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                        src.removeCallbacks(mDisallowIntercept);
132369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    }
132469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                    break;
1325ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1326ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1327ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            return false;
1328ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
1329ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1330ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        /**
1331ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * Handled forwarded motion events and determines when to stop
1332ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * forwarding.
1333ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         *
1334ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @param srcEvent motion event in source view coordinates
1335ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         * @return true to continue forwarding motion events, false to cancel
1336ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette         */
133769960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private boolean onTouchForwarded(MotionEvent srcEvent) {
133869960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            final View src = mSrc;
1339ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final ListPopupWindow popup = getPopup();
1340ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (popup == null || !popup.isShowing()) {
1341ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                return false;
1342ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1343ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1344ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final DropDownListView dst = popup.mDropDownList;
1345ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            if (dst == null || !dst.isShown()) {
1346ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette                return false;
1347ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            }
1348ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1349ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            // Convert event to destination-local coordinates.
1350ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final MotionEvent dstEvent = MotionEvent.obtainNoHistory(srcEvent);
1351ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            src.toGlobalMotionEvent(dstEvent);
1352ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            dst.toLocalMotionEvent(dstEvent);
1353ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1354ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            // Forward converted event to destination view, then recycle it.
1355ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            final boolean handled = dst.onForwardedEvent(dstEvent, mActivePointerId);
1356ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            dstEvent.recycle();
1357ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette            return handled;
1358ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette        }
135969960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette
136069960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        private class DisallowIntercept implements Runnable {
136169960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            @Override
136269960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            public void run() {
136369960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                final ViewParent parent = mSrc.getParent();
136469960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette                parent.requestDisallowInterceptTouchEvent(true);
136569960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette            }
136669960142efa8d228adbfcbabdcf618426e31e1f5Alan Viverette        }
1367ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette    }
1368ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette
1369ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette    /**
1370c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * <p>Wrapper class for a ListView. This wrapper can hijack the focus to
1371c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * make sure the list uses the appropriate drawables and states when
1372c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * displayed on screen within a drop down. The focus is never actually
1373c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * passed to the drop down in this mode; the list only looks focused.</p>
1374c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
1375c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static class DropDownListView extends ListView {
1376c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /** Duration in milliseconds of the drag-to-open click animation. */
1377c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private static final long CLICK_ANIM_DURATION = 150;
1378c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1379c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /** Target alpha value for drag-to-open click animation. */
1380c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private static final int CLICK_ANIM_ALPHA = 0x80;
1381c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1382c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /** Wrapper around Drawable's <code>alpha</code> property. */
1383c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private static final IntProperty<Drawable> DRAWABLE_ALPHA =
1384c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                new IntProperty<Drawable>("alpha") {
1385c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    @Override
1386c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    public void setValue(Drawable object, int value) {
1387c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        object.setAlpha(value);
1388c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    }
1389c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1390c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    @Override
1391c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    public Integer get(Drawable object) {
1392c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        return object.getAlpha();
1393c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    }
1394c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                };
1395c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1396c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /*
1397c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * WARNING: This is a workaround for a touch mode issue.
1398c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1399c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * Touch mode is propagated lazily to windows. This causes problems in
1400c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * the following scenario:
1401c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * - Type something in the AutoCompleteTextView and get some results
1402c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * - Move down with the d-pad to select an item in the list
1403c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * - Move up with the d-pad until the selection disappears
1404c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * - Type more text in the AutoCompleteTextView *using the soft keyboard*
1405c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *   and get new results; you are now in touch mode
1406c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * - The selection comes back on the first item in the list, even though
1407c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *   the list is supposed to be in touch mode
1408c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1409c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * Using the soft keyboard triggers the touch mode change but that change
1410c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * is propagated to our window only after the first list layout, therefore
1411c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * after the list attempts to resurrect the selection.
1412c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1413c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * The trick to work around this issue is to pretend the list is in touch
1414c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * mode when we know that the selection should not appear, that is when
1415c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * we know the user moved the selection away from the list.
1416c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1417c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * This boolean is set to true whenever we explicitly hide the list's
1418c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * selection and reset to false whenever we know the user moved the
1419c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * selection back to the list.
1420c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1421c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * When this boolean is true, isInTouchMode() returns true, otherwise it
1422c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * returns super.isInTouchMode().
1423c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1424c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private boolean mListSelectionHidden;
1425c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1426c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1427c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * True if this wrapper should fake focus.
1428c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1429c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private boolean mHijackFocus;
1430c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1431c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /** Whether to force drawing of the pressed state selector. */
1432c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private boolean mDrawsInPressedState;
1433c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1434c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /** Current drag-to-open click animation, if any. */
1435c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private Animator mClickAnimation;
1436c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
14375e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette        /** Helper for drag-to-open auto scrolling. */
14385e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette        private AbsListViewAutoScroller mScrollHelper;
14395e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette
1440c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1441c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * <p>Creates a new list view wrapper.</p>
1442c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1443c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @param context this view's context
1444c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1445c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public DropDownListView(Context context, boolean hijackFocus) {
1446c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            super(context, null, com.android.internal.R.attr.dropDownListViewStyle);
1447c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mHijackFocus = hijackFocus;
1448b1818e83f4a81bc4e4e30b99bb48830415be731bAmith Yamasani            // TODO: Add an API to control this
1449b1818e83f4a81bc4e4e30b99bb48830415be731bAmith Yamasani            setCacheColorHint(0); // Transparent, since the background drawable could be anything.
1450c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1451c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1452c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1453c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         * Handles forwarded events.
1454c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         *
1455c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         * @param activePointerId id of the pointer that activated forwarding
1456c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         * @return whether the event was handled
1457c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         */
1458c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        public boolean onForwardedEvent(MotionEvent event, int activePointerId) {
1459c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            boolean handledEvent = true;
1460c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            boolean clearPressedItem = false;
1461c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1462c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            final int actionMasked = event.getActionMasked();
1463c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            switch (actionMasked) {
1464c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                case MotionEvent.ACTION_CANCEL:
1465c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    handledEvent = false;
1466c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    break;
1467c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                case MotionEvent.ACTION_UP:
1468c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    handledEvent = false;
1469c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    // $FALL-THROUGH$
1470c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                case MotionEvent.ACTION_MOVE:
1471c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    final int activeIndex = event.findPointerIndex(activePointerId);
1472c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    if (activeIndex < 0) {
1473c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        handledEvent = false;
1474c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        break;
1475c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    }
1476c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1477c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    final int x = (int) event.getX(activeIndex);
1478c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    final int y = (int) event.getY(activeIndex);
1479c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    final int position = pointToPosition(x, y);
1480c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    if (position == INVALID_POSITION) {
1481c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        clearPressedItem = true;
1482c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        break;
1483c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    }
1484c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1485c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    final View child = getChildAt(position - getFirstVisiblePosition());
1486c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    setPressedItem(child, position);
1487c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    handledEvent = true;
1488c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1489c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    if (actionMasked == MotionEvent.ACTION_UP) {
1490c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                        clickPressedItem(child, position);
1491c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    }
1492c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    break;
1493c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            }
1494c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1495c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // Failure to handle the event cancels forwarding.
1496c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            if (!handledEvent || clearPressedItem) {
1497c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                clearPressedItem();
1498c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            }
1499c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
15005e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette            // Manage automatic scrolling.
15015e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette            if (handledEvent) {
15025e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                if (mScrollHelper == null) {
15035e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                    mScrollHelper = new AbsListViewAutoScroller(this);
15045e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                }
15055e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                mScrollHelper.setEnabled(true);
15065e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                mScrollHelper.onTouch(this, event);
15075e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette            } else if (mScrollHelper != null) {
15085e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette                mScrollHelper.setEnabled(false);
15095e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette            }
15105e66021c8a24c27c470cc6b9fe49e5653f3fa05dAlan Viverette
1511c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            return handledEvent;
1512c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        }
1513c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1514c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /**
1515c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         * Starts an alpha animation on the selector. When the animation ends,
1516c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         * the list performs a click on the item.
1517c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette         */
1518c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private void clickPressedItem(final View child, final int position) {
1519c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            final long id = getItemIdAtPosition(position);
1520c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            final Animator anim = ObjectAnimator.ofInt(
1521c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    mSelector, DRAWABLE_ALPHA, 0xFF, CLICK_ANIM_ALPHA, 0xFF);
1522c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            anim.setDuration(CLICK_ANIM_DURATION);
1523c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            anim.setInterpolator(new AccelerateDecelerateInterpolator());
1524c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            anim.addListener(new AnimatorListenerAdapter() {
1525c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    @Override
1526c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                public void onAnimationEnd(Animator animation) {
1527c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                    performItemClick(child, position, id);
1528c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                }
1529c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            });
1530c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            anim.start();
1531c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1532c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            if (mClickAnimation != null) {
1533c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                mClickAnimation.cancel();
1534c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            }
1535c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            mClickAnimation = anim;
1536c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        }
1537c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1538c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private void clearPressedItem() {
1539c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            mDrawsInPressedState = false;
1540c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            setPressed(false);
1541c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            updateSelectorState();
1542c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1543c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            if (mClickAnimation != null) {
1544c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                mClickAnimation.cancel();
1545c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                mClickAnimation = null;
1546c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            }
1547c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        }
1548c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1549c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        private void setPressedItem(View child, int position) {
1550c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            mDrawsInPressedState = true;
1551c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1552c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // Ordering is essential. First update the pressed state and layout
1553c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // the children. This will ensure the selector actually gets drawn.
1554c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            setPressed(true);
1555c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            layoutChildren();
1556c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1557c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // Ensure that keyboard focus starts from the last touched position.
1558c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            setSelectedPositionInt(position);
1559c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            positionSelector(position, child);
1560c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1561c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // Refresh the drawable state to reflect the new pressed state,
1562c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            // which will also update the selector state.
1563c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            refreshDrawableState();
1564c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1565c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            if (mClickAnimation != null) {
1566c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                mClickAnimation.cancel();
1567c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette                mClickAnimation = null;
1568c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            }
1569c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        }
1570c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1571c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        @Override
1572c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        boolean touchModeDrawsInPressedState() {
1573c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette            return mDrawsInPressedState || super.touchModeDrawsInPressedState();
1574c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        }
1575c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette
1576c05027214f1f4dda67296a072dfc9af9176dc590Alan Viverette        /**
1577c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * <p>Avoids jarring scrolling effect by ensuring that list elements
1578c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * made of a text view fit on a single line.</p>
1579c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1580c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @param position the item index in the list to get a view for
1581c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @return the view for the specified item
1582c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1583c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1584c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        View obtainView(int position, boolean[] isScrap) {
1585c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            View view = super.obtainView(position, isScrap);
1586c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1587c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (view instanceof TextView) {
1588c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                ((TextView) view).setHorizontallyScrolling(true);
1589c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1590c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1591c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return view;
1592c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1593c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1594c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1595c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean isInTouchMode() {
1596c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            // WARNING: Please read the comment where mListSelectionHidden is declared
1597c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode();
1598c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1599c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1600c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1601c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * <p>Returns the focus state in the drop down.</p>
1602c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1603c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @return true always if hijacking focus
1604c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1605c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1606c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean hasWindowFocus() {
1607c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mHijackFocus || super.hasWindowFocus();
1608c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1609c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1610c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1611c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * <p>Returns the focus state in the drop down.</p>
1612c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1613c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @return true always if hijacking focus
1614c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1615c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1616c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean isFocused() {
1617c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mHijackFocus || super.isFocused();
1618c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1619c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1620c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
1621c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * <p>Returns the focus state in the drop down.</p>
1622c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         *
1623c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @return true always if hijacking focus
1624c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
1625c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1626c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean hasFocus() {
1627c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mHijackFocus || super.hasFocus();
1628c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1629c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1630c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1631c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupDataSetObserver extends DataSetObserver {
1632c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1633c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onChanged() {
1634c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (isShowing()) {
1635c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                // Resize the popup to fit new content
1636c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                show();
1637c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1638c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1639c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1640c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        @Override
1641c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onInvalidated() {
1642c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dismiss();
1643c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1644c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1645c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1646c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class ListSelectorHider implements Runnable {
1647c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void run() {
1648c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            clearListSelection();
1649c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1650c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1651c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1652c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class ResizePopupRunnable implements Runnable {
1653c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void run() {
1654348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell            if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() &&
1655348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell                    mDropDownList.getChildCount() <= mListItemExpandMaximum) {
1656348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell                mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
1657348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell                show();
1658348e69cfabec21ccfbe708df06f0a7ea541a3053Adam Powell            }
1659c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1660c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1661c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1662c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupTouchInterceptor implements OnTouchListener {
1663c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean onTouch(View v, MotionEvent event) {
1664c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int action = event.getAction();
1665c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int x = (int) event.getX();
1666c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            final int y = (int) event.getY();
1667c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1668c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (action == MotionEvent.ACTION_DOWN &&
1669c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    mPopup != null && mPopup.isShowing() &&
1670711734a2f8d7529df0ed1bce36da651fc835c144Gilles Debunne                    (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) {
1671c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT);
1672c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            } else if (action == MotionEvent.ACTION_UP) {
1673c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.removeCallbacks(mResizePopupRunnable);
1674c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1675c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return false;
1676c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1677c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1678c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1679c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class PopupScrollListener implements ListView.OnScrollListener {
1680c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
1681c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                int totalItemCount) {
1682c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1683c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1684c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1685c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onScrollStateChanged(AbsListView view, int scrollState) {
1686c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (scrollState == SCROLL_STATE_TOUCH_SCROLL &&
1687c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    !isInputMethodNotNeeded() && mPopup.getContentView() != null) {
1688c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mHandler.removeCallbacks(mResizePopupRunnable);
1689c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mResizePopupRunnable.run();
1690c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
1691c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1692c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
1693c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell}
1694