13565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/*
23565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Copyright (C) 2010 The Android Open Source Project
33565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
43565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Licensed under the Apache License, Version 2.0 (the "License");
53565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * you may not use this file except in compliance with the License.
63565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * You may obtain a copy of the License at
73565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
83565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *      http://www.apache.org/licenses/LICENSE-2.0
93565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Unless required by applicable law or agreed to in writing, software
113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * distributed under the License is distributed on an "AS IS" BASIS,
123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * See the License for the specific language governing permissions and
143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * limitations under the License.
153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */
163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.widget;
183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.content.Context;
203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.content.res.Resources;
213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.database.DataSetObserver;
223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.Rect;
233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.drawable.Drawable;
243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.os.Handler;
25da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.text.TextUtils;
273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.AttributeSet;
283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.Log;
293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.SparseArray;
303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.KeyEvent;
313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.MotionEvent;
323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View;
333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.MeasureSpec;
343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.OnTouchListener;
353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewGroup;
363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewParent;
373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.widget.*;
383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport java.lang.reflect.Field;
403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport java.util.ArrayList;
413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport java.util.List;
423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport java.util.Locale;
433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/**
4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * A ListPopupWindow anchors itself to a host view and displays a list of choices.
463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * <p>ListPopupWindow contains a number of tricky behaviors surrounding positioning, scrolling
4820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * parents to fit the dropdown, interacting sanely with the IME if present, and others.
493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani *
503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see android.widget.AutoCompleteTextView
513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see android.widget.Spinner
5289208232f3b5d1451408d787872504a190bc7ee0Chris Banes *
5389208232f3b5d1451408d787872504a190bc7ee0Chris Banes * @hide
543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */
553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewanipublic class ListPopupWindow {
5620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final String TAG = "ListPopupWindow";
583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final boolean DEBUG = false;
593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * This value controls the length of time that the user must leave a pointer down without
6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * scrolling to expand the autocomplete dropdown list to cover the IME.
633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static final int EXPAND_LIST_TIMEOUT = 250;
653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Context mContext;
673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private PopupWindow mPopup;
683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private ListAdapter mAdapter;
693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private DropDownListView mDropDownList;
703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT;
723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownHorizontalOffset;
743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mDropDownVerticalOffset;
753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mDropDownVerticalOffsetSet;
763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mDropDownAlwaysVisible = false;
783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mForceIgnoreOutsideTouch = false;
793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    int mListItemExpandMaximum = Integer.MAX_VALUE;
803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private View mPromptView;
823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mPromptPosition = POSITION_PROMPT_ABOVE;
833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private DataSetObserver mObserver;
853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private View mDropDownAnchorView;
873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Drawable mDropDownListHighlight;
893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private AdapterView.OnItemClickListener mItemClickListener;
913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private AdapterView.OnItemSelectedListener mItemSelectedListener;
923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable();
943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor();
953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final PopupScrollListener mScrollListener = new PopupScrollListener();
963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private final ListSelectorHider mHideSelector = new ListSelectorHider();
973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Runnable mShowDropDownRunnable;
983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Handler mHandler = new Handler();
1003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private Rect mTempRect = new Rect();
1023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private boolean mModal;
1043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int mLayoutDirection;
1063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
1083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * The provided prompt view should appear above list content.
1093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptPosition(int)
1113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getPromptPosition()
1123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptView(View)
1133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int POSITION_PROMPT_ABOVE = 0;
1153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
1173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * The provided prompt view should appear below list content.
1183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptPosition(int)
1203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getPromptPosition()
1213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setPromptView(View)
1223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int POSITION_PROMPT_BELOW = 1;
1243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
12620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Alias for {@link ViewGroup.LayoutParams#FILL_PARENT}. If used to specify a popup width, the
12720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * popup will match the width of the anchor view. If used to specify a popup height, the popup
12820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * will fill available space.
1293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int FILL_PARENT = ViewGroup.LayoutParams.FILL_PARENT;
1313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}. If used to specify a popup width, the
13420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * popup will use the width of its content.
1353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT;
1373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
13920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Mode for {@link #setInputMethodMode(int)}: the requirements for the input method should be
14020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * based on the focusability of the popup.  That is if it is focusable than it needs to work
14120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * with the input method, else it doesn't.
1423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE;
1443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
14620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to work with an input
14720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * method, regardless of whether it is focusable.  This means that it will always be displayed
14820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * so that the user can also operate the input method while it is shown.
1493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED;
1513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
15320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to work with an input
15420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * method, regardless of whether it is focusable.  This means that it will always be displayed
15520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * to use as much space on the screen as needed, regardless of whether this covers the input
15620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * method.
1573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public static final int INPUT_METHOD_NOT_NEEDED = PopupWindow.INPUT_METHOD_NOT_NEEDED;
1593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
16120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Create a new, empty popup window capable of displaying items from a ListAdapter. Backgrounds
16220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * should be set using {@link #setBackgroundDrawable(Drawable)}.
1633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param context Context used for contained views.
1653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public ListPopupWindow(Context context) {
167ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns        this(context, null, R.attr.listPopupWindowStyle);
1683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
1693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
17120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Create a new, empty popup window capable of displaying items from a ListAdapter. Backgrounds
17220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * should be set using {@link #setBackgroundDrawable(Drawable)}.
1733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
1743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param context Context used for contained views.
17520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param attrs   Attributes from inflating parent views used to style the popup.
1763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public ListPopupWindow(Context context, AttributeSet attrs) {
178ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns        this(context, attrs, R.attr.listPopupWindowStyle);
1793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
1803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
18220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Create a new, empty popup window capable of displaying items from a ListAdapter. Backgrounds
18320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * should be set using {@link #setBackgroundDrawable(Drawable)}.
1843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
18520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param context      Context used for contained views.
18620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param attrs        Attributes from inflating parent views used to style the popup.
1873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param defStyleAttr Default style attribute to use for popup content.
1883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
1893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public ListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
1903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mContext = context;
191ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns        mPopup = new PopupWindow(context, attrs, defStyleAttr);
1923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
1933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // Set the default layout direction to match the default locale one
1943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final Locale locale = mContext.getResources().getConfiguration().locale;
1953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
196ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns    }
1973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
1983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
19920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the adapter that provides the data and the views to represent the data in this popup
20020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * window.
2013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param adapter The adapter to use to create this window's content.
2033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setAdapter(ListAdapter adapter) {
2053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mObserver == null) {
2063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mObserver = new PopupDataSetObserver();
2073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else if (mAdapter != null) {
2083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mAdapter.unregisterDataSetObserver(mObserver);
2093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mAdapter = adapter;
2113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mAdapter != null) {
2123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            adapter.registerDataSetObserver(mObserver);
2133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mDropDownList != null) {
2163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setAdapter(mAdapter);
2173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
2183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
22120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Set where the optional prompt view should appear. The default is {@link
22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #POSITION_PROMPT_ABOVE}.
2233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position A position constant declaring where the prompt should be displayed.
2253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_ABOVE
2263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_BELOW
2273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setPromptPosition(int position) {
2293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPromptPosition = position;
2303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Where the optional prompt view should appear.
2343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_ABOVE
2353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #POSITION_PROMPT_BELOW
2363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getPromptPosition() {
2383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPromptPosition;
2393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set whether this window should be modal when shown.
2433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
24420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * <p>If a popup window is modal, it will receive all touch and key input. If the user touches
24520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * outside the popup window's content area the popup window will be dismissed.
2463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param modal {@code true} if the popup window should be modal, {@code false} otherwise.
2483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setModal(boolean modal) {
2503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mModal = true;
2513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setFocusable(modal);
2523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns whether the popup window will be modal when shown.
2563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return {@code true} if the popup window will be modal, {@code false} otherwise.
2583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isModal() {
2603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mModal;
2613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is
26520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we ignore
26620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * outside touch even when the drop down is not set to always visible.
2673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Used only by AutoCompleteTextView to handle some internal special cases.
2693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) {
2713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch;
2723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets whether the drop-down should remain visible under certain conditions.
2763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
27720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless of the
27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * size or content of the list.  {@link #getBackground()} will fill any space that is not used
27920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * by the list.
2803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
2813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param dropDownAlwaysVisible Whether to keep the drop-down visible.
2823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Only used by AutoCompleteTextView under special conditions.
2833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) {
2853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownAlwaysVisible = dropDownAlwaysVisible;
2863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Whether the drop-down is visible under special conditions.
2903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Only used by AutoCompleteTextView under special conditions.
2913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
2923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isDropDownAlwaysVisible() {
2933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownAlwaysVisible;
2943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
2953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
2963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
2973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets the operating mode for the soft input area.
2983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
29920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param mode The desired mode, see {@link android.view.WindowManager.LayoutParams#softInputMode}
30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *             for the full list
3013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see android.view.WindowManager.LayoutParams#softInputMode
3023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getSoftInputMode()
3033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setSoftInputMode(int mode) {
3053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setSoftInputMode(mode);
3063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns the current value in {@link #setSoftInputMode(int)}.
3103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setSoftInputMode(int)
3123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see android.view.WindowManager.LayoutParams#softInputMode
3133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getSoftInputMode() {
3153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getSoftInputMode();
3163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a drawable to use as the list item selector.
3203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param selector List selector drawable to use in the popup.
3223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setListSelector(Drawable selector) {
3243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownListHighlight = selector;
3253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The background drawable for the popup window.
3293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public Drawable getBackground() {
3313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getBackground();
3323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a drawable to be the background for the popup window.
3363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param d A drawable to set as the background.
3383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setBackgroundDrawable(Drawable d) {
3403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setBackgroundDrawable(d);
3413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set an animation style to use when the popup window is shown or dismissed.
3453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param animationStyle Animation style to use.
3473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setAnimationStyle(int animationStyle) {
3493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setAnimationStyle(animationStyle);
3503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
35320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Returns the animation style that will be used when the popup window is shown or dismissed.
3543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return Animation style that will be used.
3563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getAnimationStyle() {
3583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getAnimationStyle();
3593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Returns the view that will be used to anchor this popup.
3633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The popup's anchor view
3653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public View getAnchorView() {
3673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownAnchorView;
3683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
37120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the popup's anchor view. This popup will always be positioned relative to the anchor
37220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * view when shown.
3733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param anchor The view to use as an anchor.
3753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setAnchorView(View anchor) {
3773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownAnchorView = anchor;
3783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The horizontal offset of the popup from its anchor in pixels.
3823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getHorizontalOffset() {
3843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownHorizontalOffset;
3853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set the horizontal offset of this popup from its anchor view in pixels.
3893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
3903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param offset The horizontal offset of the popup from its anchor.
3913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setHorizontalOffset(int offset) {
3933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownHorizontalOffset = offset;
3943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
3953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
3963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
3973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The vertical offset of the popup from its anchor in pixels.
3983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
3993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getVerticalOffset() {
4003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!mDropDownVerticalOffsetSet) {
4013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return 0;
4023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
4033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownVerticalOffset;
4043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set the vertical offset of this popup from its anchor view in pixels.
4083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param offset The vertical offset of the popup from its anchor.
4103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setVerticalOffset(int offset) {
4123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownVerticalOffset = offset;
4133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownVerticalOffsetSet = true;
4143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The width of the popup window in pixels.
4183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getWidth() {
4203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownWidth;
4213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
42420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the width of the popup window in pixels. Can also be {@link #FILL_PARENT} or {@link
42520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #WRAP_CONTENT}.
4263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param width Width of the popup window.
4283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setWidth(int width) {
4303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownWidth = width;
4313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
43420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Sets the width of the popup window by the size of its content. The final width may be larger
43520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * to accommodate styled window dressing.
4363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param width Desired width of content in pixels.
4383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setContentWidth(int width) {
4403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        Drawable popupBackground = mPopup.getBackground();
4413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (popupBackground != null) {
4423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            popupBackground.getPadding(mTempRect);
4433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownWidth = mTempRect.left + mTempRect.right + width;
4443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
4453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            setWidth(width);
4463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
4473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The height of the popup window in pixels.
4513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getHeight() {
4533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownHeight;
4543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets the height of the popup window in pixels. Can also be {@link #FILL_PARENT}.
4583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param height Height of the popup window.
4603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setHeight(int height) {
4623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownHeight = height;
4633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a listener to receive events when a list item is clicked.
4673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param clickListener Listener to register
4693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)
4703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setOnItemClickListener(AdapterView.OnItemClickListener clickListener) {
4723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mItemClickListener = clickListener;
4733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Sets a listener to receive events when a list item is selected.
4773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param selectedListener Listener to register.
4793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener)
4803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener selectedListener) {
4823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mItemSelectedListener = selectedListener;
4833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
4843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
4853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
4863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set a view to act as a user prompt for this popup window. Where the prompt view will appear
4873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * is controlled by {@link #setPromptPosition(int)}.
4883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
4893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param prompt View to use as an informational prompt.
4903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
4913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setPromptView(View prompt) {
4923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        boolean showing = isShowing();
4933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (showing) {
4943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            removePromptView();
4953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
4963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPromptView = prompt;
4973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (showing) {
4983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            show();
4993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
5003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
5033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Post a {@link #show()} call to the UI thread.
5043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void postShow() {
5063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mHandler.post(mShowDropDownRunnable);
5073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
51020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Show the popup list. If the list is already showing, this method will recalculate the popup's
51120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * size and position.
5123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void show() {
5143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int height = buildDropDown();
5153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int widthSpec = 0;
5173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int heightSpec = 0;
5183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        boolean noInputMethod = isInputMethodNotNeeded();
5203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mPopup.isShowing()) {
5223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
5233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // The call to PopupWindow's update method below can accept -1 for any
5243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // value you do not want to update.
5253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = -1;
5263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
5273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = getAnchorView().getWidth();
5283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
5293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = mDropDownWidth;
5303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
5333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // The call to PopupWindow's update method below can accept -1 for any
5343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // value you do not want to update.
5353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.FILL_PARENT;
5363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (noInputMethod) {
5373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setWindowLayoutMode(
5383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
5393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                                    ViewGroup.LayoutParams.FILL_PARENT : 0, 0);
5403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
5413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setWindowLayoutMode(
5423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
5433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                                    ViewGroup.LayoutParams.FILL_PARENT : 0,
5443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            ViewGroup.LayoutParams.FILL_PARENT);
5453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
5463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
5473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = height;
5483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
5493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = mDropDownHeight;
5503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
5533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.update(getAnchorView(), mDropDownHorizontalOffset,
5553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownVerticalOffset, widthSpec, heightSpec);
5563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
5573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
5583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                widthSpec = ViewGroup.LayoutParams.FILL_PARENT;
5593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
5603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
5613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setWidth(getAnchorView().getWidth());
5623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
5633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setWidth(mDropDownWidth);
5643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
5653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
5683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                heightSpec = ViewGroup.LayoutParams.FILL_PARENT;
5693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
5703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
5713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setHeight(height);
5723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
5733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setHeight(mDropDownHeight);
5743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
5753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setWindowLayoutMode(widthSpec, heightSpec);
5783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // use outside touchable to dismiss drop down when touching outside of it, so
5803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // only set this if the dropdown is not always visible
5813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
5823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setTouchInterceptor(mTouchInterceptor);
5833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.showAsDropDown(getAnchorView(),
5843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownHorizontalOffset, mDropDownVerticalOffset);
5853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setSelection(ListView.INVALID_POSITION);
5863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mModal || mDropDownList.isInTouchMode()) {
5883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                clearListSelection();
5893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mModal) {
5913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.post(mHideSelector);
5923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
5933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
5943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
5953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
5963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
5973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Dismiss the popup window.
5983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
5993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void dismiss() {
6003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.dismiss();
6013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        removePromptView();
6023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setContentView(null);
6033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mDropDownList = null;
6043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mHandler.removeCallbacks(mResizePopupRunnable);
6053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Set a listener to receive a callback when the popup is dismissed.
6093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param listener Listener that will be notified when the popup is dismissed.
6113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
6133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setOnDismissListener(listener);
6143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private void removePromptView() {
6173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mPromptView != null) {
6183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final ViewParent parent = mPromptView.getParent();
6193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (parent instanceof ViewGroup) {
6203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ViewGroup group = (ViewGroup) parent;
6213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                group.removeView(mPromptView);
6223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
6243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
62720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Control how the popup operates with an input method: one of {@link
62820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED}, or {@link
62920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * #INPUT_METHOD_NOT_NEEDED}.
6303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
63120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * <p>If the popup is showing, calling this method will take effect only the next time the popup
63220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * is shown or through a manual call to the {@link #show()} method.</p>
6333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #getInputMethodMode()
6353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #show()
6363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setInputMethodMode(int mode) {
6383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mPopup.setInputMethodMode(mode);
6393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Return the current value in {@link #setInputMethodMode(int)}.
6433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setInputMethodMode(int)
6453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getInputMethodMode() {
6473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getInputMethodMode();
6483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
65120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Set the selected position of the list. Only valid when {@link #isShowing()} == {@code true}.
6523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position List position to set as selected.
6543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void setSelection(int position) {
6563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        DropDownListView list = mDropDownList;
6573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing() && list != null) {
6583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.mListSelectionHidden = false;
6593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.setSelection(position);
6603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) {
6613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                list.setItemChecked(position, true);
6623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
6633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
6643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
66720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Clear any current list selection. Only valid when {@link #isShowing()} == {@code true}.
6683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public void clearListSelection() {
6703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final DropDownListView list = mDropDownList;
6713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (list != null) {
6723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // WARNING: Please read the comment where mListSelectionHidden is declared
6733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.mListSelectionHidden = true;
6743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            //list.hideSelector();
6753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            list.requestLayout();
6763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
6773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return {@code true} if the popup is currently showing, {@code false} otherwise.
6813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isShowing() {
6833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.isShowing();
6843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
68720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return {@code true} if this popup is configured to assume the user does not need to interact
68820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         with the IME while it is showing, {@code false} otherwise.
6893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
6903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean isInputMethodNotNeeded() {
6913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mPopup.getInputMethodMode() == INPUT_METHOD_NOT_NEEDED;
6923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
6933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
6943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
6953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Perform an item click operation on the specified list adapter position.
6963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
6973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param position Adapter position for performing the click
69820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return true if the click action could be performed, false if not. (e.g. if the popup was not
69920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         showing, this method would return false.)
7003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean performItemClick(int position) {
7023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing()) {
7033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mItemClickListener != null) {
7043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final DropDownListView list = mDropDownList;
7053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final View child = list.getChildAt(position - list.getFirstVisiblePosition());
7063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ListAdapter adapter = list.getAdapter();
7073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mItemClickListener.onItemClick(list, child, position, adapter.getItemId(position));
7083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
7093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return true;
7103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
7123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
7153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return The currently selected item or null if the popup is not showing.
7163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public Object getSelectedItem() {
7183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
7193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return null;
7203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItem();
7223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
72520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return The position of the currently selected item or {@link ListView#INVALID_POSITION} if
72620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         {@link #isShowing()} == {@code false}.
7273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedItemPosition()
7283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getSelectedItemPosition() {
7303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
7313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return ListView.INVALID_POSITION;
7323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItemPosition();
7343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
73720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID} if {@link
73820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         #isShowing()} == {@code false}.
7393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedItemId()
7403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public long getSelectedItemId() {
7423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
7433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return ListView.INVALID_ROW_ID;
7443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedItemId();
7463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
74920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return The View for the currently selected item or null if {@link #isShowing()} == {@code
75020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         false}.
7513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see ListView#getSelectedView()
7523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public View getSelectedView() {
7543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (!isShowing()) {
7553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return null;
7563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
7573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList.getSelectedView();
7583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
76120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return The {@link ListView} displayed within the popup window. Only valid when {@link
76220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *         #isShowing()} == {@code true}.
7633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public ListView getListView() {
7653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return mDropDownList;
7663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
76920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * The maximum number of list items that can be visible and still have the list expand when
77020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * touched.
7713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param max Max number of items that can be visible and still allow the list to expand.
7733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    void setListItemExpandMax(int max) {
7753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        mListItemExpandMaximum = max;
7763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
7773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
7783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
77920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Filter key down events. By forwarding key down events to this function, views using non-modal
78020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * ListPopupWindow can have it handle key selection of items.
7813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
7823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param keyCode keyCode param passed to the host view's onKeyDown
78320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param event   event param passed to the host view's onKeyDown
7843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return true if the event was handled, false if it was ignored.
7853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setModal(boolean)
7863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
7873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean onKeyDown(int keyCode, KeyEvent event) {
7883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // when the drop down is shown, we drive it directly
7893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing()) {
7903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // the key events are forwarded to the list in the drop down view
7913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // note that ListView handles space but we don't want that to happen
7923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // also if selection is not currently in the drop down, then don't
7933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // let center or enter presses go there since that would cause it
7943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // to select one of its items
7953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (keyCode != KeyEvent.KEYCODE_SPACE
7963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    && (mDropDownList.getSelectedItemPosition() >= 0
7973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    || (keyCode != KeyEvent.KEYCODE_ENTER
7983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    && keyCode != KeyEvent.KEYCODE_DPAD_CENTER))) {
7993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int curIndex = mDropDownList.getSelectedItemPosition();
8003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                boolean consumed;
8013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final boolean below = !mPopup.isAboveAnchor();
8033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                final ListAdapter adapter = mAdapter;
8053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                boolean allEnabled;
8073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int firstItem = Integer.MAX_VALUE;
8083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int lastItem = Integer.MIN_VALUE;
8093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (adapter != null) {
8113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    allEnabled = adapter.areAllItemsEnabled();
8123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    firstItem = allEnabled ? 0 :
813ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            mDropDownList.lookForSelectablePosition(0, true);
8143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    lastItem = allEnabled ? adapter.getCount() - 1 :
815ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false);
8163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
8173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) ||
8193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) {
8203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // When the selection is at the top, we block the key
8213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // event to prevent focus from moving.
8223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    clearListSelection();
8233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
8243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    show();
8253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    return true;
8263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
8273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // WARNING: Please read the comment where mListSelectionHidden
8283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    //          is declared
8293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownList.mListSelectionHidden = false;
8303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
8313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                consumed = mDropDownList.onKeyDown(keyCode, event);
83320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                if (DEBUG) {
83420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed);
83520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                }
8363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (consumed) {
8383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // If it handled the key event, then the user is
8393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // navigating in the list, so we should put it in front.
8403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
8413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // Here's a little trick we need to do to make sure that
8423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // the list view is actually showing its focus indicator,
8433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // by ensuring it has focus and getting its window out
8443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // of touch mode.
8453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownList.requestFocusFromTouch();
8463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    show();
8473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    switch (keyCode) {
8493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // avoid passing the focus from the text view to the
8503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // next component
8513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_ENTER:
8523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_CENTER:
8533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_DOWN:
8543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        case KeyEvent.KEYCODE_DPAD_UP:
8553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            return true;
8563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
8573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
8583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {
8593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // when the selection is at the bottom, we block the
8603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        // event to avoid going to the next focusable widget
8613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        if (curIndex == lastItem) {
8623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            return true;
8633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        }
8643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP &&
8653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            curIndex == firstItem) {
8663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        return true;
8673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
8683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
8693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
8703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
8713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
8733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
8743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
8753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
87620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Filter key down events. By forwarding key up events to this function, views using non-modal
87720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * ListPopupWindow can have it handle key selection of items.
8783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
8793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @param keyCode keyCode param passed to the host view's onKeyUp
88020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param event   event param passed to the host view's onKeyUp
8813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return true if the event was handled, false if it was ignored.
8823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @see #setModal(boolean)
8833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
8843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public boolean onKeyUp(int keyCode, KeyEvent event) {
8853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {
8863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            boolean consumed = mDropDownList.onKeyUp(keyCode, event);
8873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (consumed) {
8883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                switch (keyCode) {
8893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // if the list accepts the key events and the key event
8903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // was a click, the text view gets the selected item
8913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // from the drop down as its content
8923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case KeyEvent.KEYCODE_ENTER:
8933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case KeyEvent.KEYCODE_DPAD_CENTER:
8943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        dismiss();
8953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
8963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
8973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
8983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return consumed;
8993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
9003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return false;
9013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
9023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
90420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * <p>Builds the popup window's content and returns the height the popup should have. Returns -1
90520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * when the content already exists.</p>
9063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
9073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @return the content's height or -1 if content already exists
9083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
9093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private int buildDropDown() {
9103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        ViewGroup dropDownView;
9113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int otherHeights = 0;
9123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mDropDownList == null) {
9143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            Context context = mContext;
9153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            /**
9173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * This Runnable exists for the sole purpose of checking if the view layout has got
9183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * completed and if so call showDropDown to display the drop down. This is used to show
9193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * the drop down as soon as possible after user opens up the search dialog, without
9203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             * waiting for the normal UI pipeline to do it's job which is slower than this method.
9213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani             */
9223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mShowDropDownRunnable = new Runnable() {
9233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void run() {
9243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    // View layout should be all done before displaying the drop down.
9253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    View view = getAnchorView();
9263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (view != null && view.getWindowToken() != null) {
9273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        show();
9283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
9293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            };
9313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList = new DropDownListView(context, !mModal);
9333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownListHighlight != null) {
9343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownList.setSelector(mDropDownListHighlight);
9353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
9363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setAdapter(mAdapter);
9373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setOnItemClickListener(mItemClickListener);
9383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setFocusable(true);
9393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setFocusableInTouchMode(true);
9403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
9413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void onItemSelected(AdapterView<?> parent, View view,
94220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                        int position, long id) {
9433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    if (position != -1) {
9453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        DropDownListView dropDownList = mDropDownList;
9463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        if (dropDownList != null) {
9483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                            dropDownList.mListSelectionHidden = false;
9493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        }
9503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
9513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                public void onNothingSelected(AdapterView<?> parent) {
9543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            });
9563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mDropDownList.setOnScrollListener(mScrollListener);
9573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mItemSelectedListener != null) {
9593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownList.setOnItemSelectedListener(mItemSelectedListener);
9603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
9613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dropDownView = mDropDownList;
9633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            View hintView = mPromptView;
9653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (hintView != null) {
9663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // if a hint has been specified, we accomodate more space for it and
9673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // add a text view in the drop down menu, at the bottom of the list
9683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout hintContainer = new LinearLayout(context);
9693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintContainer.setOrientation(LinearLayout.VERTICAL);
9703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams(
9723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        ViewGroup.LayoutParams.FILL_PARENT, 0, 1.0f
9733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                );
9743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                switch (mPromptPosition) {
9763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case POSITION_PROMPT_BELOW:
9773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(dropDownView, hintParams);
9783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(hintView);
9793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
9803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    case POSITION_PROMPT_ABOVE:
9823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(hintView);
9833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        hintContainer.addView(dropDownView, hintParams);
9843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
9853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    default:
9873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        Log.e(TAG, "Invalid hint position " + mPromptPosition);
9883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        break;
9893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
9903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // measure the hint's height to find how much more vertical space
9923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // we need to add to the drop down's height
9933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int widthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.AT_MOST);
9943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                int heightSpec = MeasureSpec.UNSPECIFIED;
9953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintView.measure(widthSpec, heightSpec);
9963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
9973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams();
9983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin
9993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        + hintParams.bottomMargin;
10003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                dropDownView = hintContainer;
10023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
10033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.setContentView(dropDownView);
10053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
10063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dropDownView = (ViewGroup) mPopup.getContentView();
10073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final View view = mPromptView;
10083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (view != null) {
10093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                LinearLayout.LayoutParams hintParams =
10103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        (LinearLayout.LayoutParams) view.getLayoutParams();
10113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                otherHeights = view.getMeasuredHeight() + hintParams.topMargin
10123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        + hintParams.bottomMargin;
10133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
10143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
10153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // getMaxAvailableHeight() subtracts the padding, so we put it back
10173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // to get the available height for the whole window
10183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int padding = 0;
10193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        Drawable background = mPopup.getBackground();
10203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (background != null) {
10213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            background.getPadding(mTempRect);
10223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            padding = mTempRect.top + mTempRect.bottom;
10233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // If we don't have an explicit vertical offset, determine one from the window
10253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // background so that content will line up.
10263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!mDropDownVerticalOffsetSet) {
10273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mDropDownVerticalOffset = -mTempRect.top;
10283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
10293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        } else {
10303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mTempRect.setEmpty();
10313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
10323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // Max height available on the screen for a popup.
10343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        boolean ignoreBottomDecorations =
10353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
10363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int maxHeight = getMaxAvailableHeight(
1037ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
10383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
10403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return maxHeight + padding;
10413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
10423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int childWidthSpec;
10443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        switch (mDropDownWidth) {
10453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            case ViewGroup.LayoutParams.WRAP_CONTENT:
10463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(
10473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        mContext.getResources().getDisplayMetrics().widthPixels -
10483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                                (mTempRect.left + mTempRect.right),
10493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        MeasureSpec.AT_MOST);
10503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
10513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            case ViewGroup.LayoutParams.FILL_PARENT:
10523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(
10533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        mContext.getResources().getDisplayMetrics().widthPixels -
10543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                                (mTempRect.left + mTempRect.right),
10553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        MeasureSpec.EXACTLY);
10563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
10573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            default:
10583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY);
10593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                break;
10603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
1061ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
106279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int listContent = mDropDownList.measureHeightOfChildrenCompat(childWidthSpec,
10633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                0, DropDownListView.NO_POSITION, maxHeight - otherHeights, -1);
10643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // add padding only if the list has items in it, that way we don't show
10653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // the popup if it is not needed
106620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        if (listContent > 0) {
106720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            otherHeights += padding;
106820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        }
10693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return listContent + otherHeights;
10713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
10723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
10743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * Copied from PopupWindow.java of JB
10753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
107620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * Returns the maximum height that is available for the popup to be completely shown, optionally
107720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * ignoring any bottom decorations such as the input method. It is recommended that this height
107820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * be the maximum for the popup's height, otherwise it is possible that the popup will be
10793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * clipped.
10803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     *
108120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param anchor                  The view on which the popup window must be anchored.
108220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param yOffset                 y offset from the view's bottom edge
108320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @param ignoreBottomDecorations if true, the height returned will be all the way to the bottom
108420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     *                                of the display, ignoring any bottom decorations
108520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * @return The maximum available height for the popup to be completely shown.
10863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     * @hide Pending API council approval.
10873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
10883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    public int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) {
10893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final Rect displayFrame = new Rect();
10903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        anchor.getWindowVisibleDisplayFrame(displayFrame);
10913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int[] mDrawingLocation = new int[2];
10933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int[] anchorPos = mDrawingLocation;
10943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        anchor.getLocationOnScreen(anchorPos);
10953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
10963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int bottomEdge = displayFrame.bottom;
10973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (ignoreBottomDecorations) {
10983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            Resources res = anchor.getContext().getResources();
10993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            bottomEdge = res.getDisplayMetrics().heightPixels;
11003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
11013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
11023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
11033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        // anchorPos[1] is distance from anchor to top of screen
11053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        int returnedHeight = Math.max(distanceToBottom, distanceToTop);
11063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        if (mPopup.getBackground() != null) {
11073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mPopup.getBackground().getPadding(mTempRect);
11083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            returnedHeight -= mTempRect.top + mTempRect.bottom;
11093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
11103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        return returnedHeight;
11123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
11133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    /**
111520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * <p>Wrapper class for a ListView. This wrapper can hijack the focus to make sure the list uses
111620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * the appropriate drawables and states when displayed on screen within a drop down. The focus
111720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns     * is never actually passed to the drop down in this mode; the list only looks focused.</p>
11183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani     */
11193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private static class DropDownListView extends ListView {
112020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
11213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        private static final String TAG = ListPopupWindow.TAG + ".DropDownListView";
112220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
11233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /*
112420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * WARNING: This is a workaround for a touch mode issue.
112520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *
112620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * Touch mode is propagated lazily to windows. This causes problems in
112720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * the following scenario:
112820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * - Type something in the AutoCompleteTextView and get some results
112920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * - Move down with the d-pad to select an item in the list
113020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * - Move up with the d-pad until the selection disappears
113120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * - Type more text in the AutoCompleteTextView *using the soft keyboard*
113220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *   and get new results; you are now in touch mode
113320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * - The selection comes back on the first item in the list, even though
113420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *   the list is supposed to be in touch mode
113520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *
113620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * Using the soft keyboard triggers the touch mode change but that change
113720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * is propagated to our window only after the first list layout, therefore
113820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * after the list attempts to resurrect the selection.
113920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *
114020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * The trick to work around this issue is to pretend the list is in touch
114120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * mode when we know that the selection should not appear, that is when
114220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * we know the user moved the selection away from the list.
114320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *
114420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * This boolean is set to true whenever we explicitly hide the list's
114520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * selection and reset to false whenever we know the user moved the
114620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * selection back to the list.
114720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        *
114820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * When this boolean is true, isInTouchMode() returns true, otherwise it
114920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        * returns super.isInTouchMode().
115020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns        */
11513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        private boolean mListSelectionHidden;
11523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public static final int INVALID_POSITION = -1;
115520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
11563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        static final int NO_POSITION = -1;
11573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
11603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * True if this wrapper should fake focus.
11613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
11623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        private boolean mHijackFocus;
11633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
11653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * <p>Creates a new list view wrapper.</p>
11663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
11673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @param context this view's context
11683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
11693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public DropDownListView(Context context, boolean hijackFocus) {
11703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            super(context, null, R.attr.dropDownListViewStyle);
11713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            mHijackFocus = hijackFocus;
11723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            setCacheColorHint(0); // Transparent, since the background drawable could be anything.
11733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
11743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
11763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * Find a position that can be selected (i.e., is not a separator).
11773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
11783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @param position The starting position to look at.
11793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @param lookDown Whether to look down for other positions.
11803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @return The next selectable position starting at position and then searching either up or
11813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *         down. Returns {@link #INVALID_POSITION} if nothing can be found.
11823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
1183e6072e2d918169bd827cf7431347fb648124c227Jeff Brown        private int lookForSelectablePosition(int position, boolean lookDown) {
11843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final ListAdapter adapter = getAdapter();
11853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (adapter == null || isInTouchMode()) {
11863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                return INVALID_POSITION;
11873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
11883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
11893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int count = adapter.getCount();
11903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (!getAdapter().areAllItemsEnabled()) {
11913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (lookDown) {
11923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    position = Math.max(0, position);
11933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    while (position < count && !adapter.isEnabled(position)) {
11943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        position++;
11953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
11963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                } else {
11973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    position = Math.min(position, count - 1);
11983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    while (position >= 0 && !adapter.isEnabled(position)) {
11993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                        position--;
12003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    }
12013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
12023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (position < 0 || position >= count) {
12043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    return INVALID_POSITION;
12053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
12063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                return position;
12073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else {
12083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                if (position < 0 || position >= count) {
12093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    return INVALID_POSITION;
12103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                }
12113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                return position;
12123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean isInTouchMode() {
12173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // WARNING: Please read the comment where mListSelectionHidden is declared
12183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return (mHijackFocus && mListSelectionHidden) || super.isInTouchMode();
12193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
12223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * <p>Returns the focus state in the drop down.</p>
12233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
12243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @return true always if hijacking focus
12253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
12263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean hasWindowFocus() {
12283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return mHijackFocus || super.hasWindowFocus();
12293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
12323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * <p>Returns the focus state in the drop down.</p>
12333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
12343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @return true always if hijacking focus
12353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
12363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean isFocused() {
12383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return mHijackFocus || super.isFocused();
12393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
12423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * <p>Returns the focus state in the drop down.</p>
12433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
12443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @return true always if hijacking focus
12453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
12463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
12473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean hasFocus() {
12483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return mHijackFocus || super.hasFocus();
12493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
12503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        /**
125220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * Measures the height of the given range of children (inclusive) and returns the height
125320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * with this ListView's padding and divider heights included. If maxHeight is provided, the
125420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * measuring will stop when the current height reaches maxHeight.
12553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         *
125620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * @param widthMeasureSpec             The width measure spec to be given to a child's
125720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     {@link View#measure(int, int)}.
125820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * @param startPosition                The position of the first child to be shown.
125920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * @param endPosition                  The (inclusive) position of the last child to be
126020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     shown. Specify {@link #NO_POSITION} if the last child
126120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     should be the last available child from the adapter.
126220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * @param maxHeight                    The maximum height that will be returned (if all the
126320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     children don't fit in this value, this value will be
126420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     returned).
126520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         * @param disallowPartialChildPosition In general, whether the returned height should only
126620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     contain entire children. This is more powerful--it is
126720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     the first inclusive position at which partial
126820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     children will not be allowed. Example: it looks nice
126920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     to have at least 3 completely visible children, and
127020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     in portrait this will most likely fit; but in
127120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     landscape there could be times when even 2 children
127220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     can not be completely shown, so a value of 2
127320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     (remember, inclusive) would be good (assuming
127420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns         *                                     startPosition is 0).
12753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         * @return The height of this ListView with the given children.
12763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani         */
127779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int measureHeightOfChildrenCompat(int widthMeasureSpec, int startPosition,
127820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                int endPosition, final int maxHeight,
127920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                int disallowPartialChildPosition) {
1280ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1281ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final int paddingTop = getListPaddingTop();
1282ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final int paddingBottom = getListPaddingBottom();
1283ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final int paddingLeft = getListPaddingLeft();
1284ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final int paddingRight = getListPaddingRight();
1285ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final int reportedDividerHeight = getDividerHeight();
1286ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            final Drawable divider = getDivider();
12873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final ListAdapter adapter = getAdapter();
12893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (adapter == null) {
1291ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                return paddingTop + paddingBottom;
12923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
12933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
12943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            // Include the padding of the list
1295ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            int returnedHeight = paddingTop + paddingBottom;
129620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns            final int dividerHeight = ((reportedDividerHeight > 0) && divider != null)
129720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    ? reportedDividerHeight : 0;
1298ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1299ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            // The previous height value that was less than maxHeight and contained
1300ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            // no partial children
1301ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            int prevHeightWithoutPartialChild = 0;
1302ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1303ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            View child = null;
1304ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            int viewType = 0;
1305ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            int count = adapter.getCount();
1306ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            for (int i = 0; i < count; i++) {
1307ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                int newType = adapter.getItemViewType(i);
1308ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                if (newType != viewType) {
1309ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    child = null;
1310ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    viewType = newType;
1311ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                }
131220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                child = adapter.getView(i, child, this);
131320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                ;
1314ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1315ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                // Compute child height spec
1316ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                int heightMeasureSpec;
1317ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                int childHeight = child.getLayoutParams().height;
1318ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                if (childHeight > 0) {
131920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    heightMeasureSpec = MeasureSpec
132020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                            .makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
1321ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                } else {
1322ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
1323ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                }
1324ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                child.measure(widthMeasureSpec, heightMeasureSpec);
1325ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1326ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                if (i > 0) {
1327ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    // Count the divider for all but one child
1328ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    returnedHeight += dividerHeight;
1329ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                }
1330ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1331ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                returnedHeight += child.getMeasuredHeight();
1332ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1333ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                if (returnedHeight >= maxHeight) {
133420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    // We went over, figure out which height to return.  If returnedHeight >
133520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                    // maxHeight, then the i'th position did not fit completely.
1336ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1)
1337ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            && (i > disallowPartialChildPosition) // We've past the min pos
1338ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            && (prevHeightWithoutPartialChild > 0) // We have a prev height
1339ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            && (returnedHeight != maxHeight) // i'th child did not fit completely
1340ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            ? prevHeightWithoutPartialChild
1341ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                            : maxHeight;
1342ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                }
1343ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1344ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) {
1345ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                    prevHeightWithoutPartialChild = returnedHeight;
1346ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns                }
1347ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            }
1348ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns
1349ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            // At this point, we went through the range of children, and they each
1350ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns            // completely fit, so return the returnedHeight
13513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return returnedHeight;
13523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupDataSetObserver extends DataSetObserver {
135720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
13593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onChanged() {
13603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (isShowing()) {
13613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                // Resize the popup to fit new content
13623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                show();
13633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
13643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        @Override
13673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onInvalidated() {
13683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            dismiss();
13693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class ListSelectorHider implements Runnable {
137320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void run() {
13753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            clearListSelection();
13763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class ResizePopupRunnable implements Runnable {
138020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void run() {
13823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (mDropDownList != null && mDropDownList.getCount() > mDropDownList.getChildCount() &&
13833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mDropDownList.getChildCount() <= mListItemExpandMaximum) {
13843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
13853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                show();
13863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
13873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
13883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
13893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupTouchInterceptor implements OnTouchListener {
139120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
13923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public boolean onTouch(View v, MotionEvent event) {
13933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int action = event.getAction();
13943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int x = (int) event.getX();
13953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            final int y = (int) event.getY();
13963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
13973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (action == MotionEvent.ACTION_DOWN &&
13983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    mPopup != null && mPopup.isShowing() &&
13993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) {
14003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT);
14013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            } else if (action == MotionEvent.ACTION_UP) {
14023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.removeCallbacks(mResizePopupRunnable);
14033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
14043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            return false;
14053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
14063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
14073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
14083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    private class PopupScrollListener implements ListView.OnScrollListener {
140920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns
14103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
141120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns                int totalItemCount) {
14123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
14133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
14143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani
14153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        public void onScrollStateChanged(AbsListView view, int scrollState) {
14163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            if (scrollState == SCROLL_STATE_TOUCH_SCROLL &&
14173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                    !isInputMethodNotNeeded() && mPopup.getContentView() != null) {
14183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mHandler.removeCallbacks(mResizePopupRunnable);
14193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani                mResizePopupRunnable.run();
14203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani            }
14213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani        }
14223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani    }
14233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani}