13565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/* 249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project 33565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 43565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Licensed under the Apache License, Version 2.0 (the "License"); 53565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * you may not use this file except in compliance with the License. 63565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * You may obtain a copy of the License at 73565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 83565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * http://www.apache.org/licenses/LICENSE-2.0 93565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Unless required by applicable law or agreed to in writing, software 113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * distributed under the License is distributed on an "AS IS" BASIS, 123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * See the License for the specific language governing permissions and 143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * limitations under the License. 153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1749c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.widget; 183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.content.Context; 20ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport android.content.res.TypedArray; 213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.database.DataSetObserver; 223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.Rect; 233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.graphics.drawable.Drawable; 2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.os.Build; 253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.os.Handler; 266142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.AttrRes; 276142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.NonNull; 286142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.Nullable; 296142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.annotation.StyleRes; 306142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v4.os.BuildCompat; 3118864e53490e04739f1063a7ee113549874f87b0Chris Banesimport android.support.v4.view.ViewCompat; 3249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v4.widget.PopupWindowCompat; 33da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R; 346142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.support.v7.view.menu.ShowableListMenu; 353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.AttributeSet; 363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.util.Log; 3749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Gravity; 383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.KeyEvent; 393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.MotionEvent; 403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View; 413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.MeasureSpec; 423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.View.OnTouchListener; 433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewGroup; 443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewaniimport android.view.ViewParent; 4518864e53490e04739f1063a7ee113549874f87b0Chris Banesimport android.view.WindowManager; 4649c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.AbsListView; 4749c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.AdapterView; 486142a54baae3289f734947c6b5375b12eb0fb722Chris Banesimport android.widget.AdapterView.OnItemSelectedListener; 4949c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.LinearLayout; 5049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.ListAdapter; 5149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.ListView; 5249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.widget.PopupWindow; 533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 54ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banesimport java.lang.reflect.Method; 553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani/** 5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Static library support version of the framework's {@link android.widget.ListPopupWindow}. 5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Used to write apps that run on platforms prior to Android L. When running 5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * on Android L or above, this implementation is still used; it does not try 6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to switch to the framework's implementation. See the framework SDK 6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * documentation for a class overview. 623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see android.widget.ListPopupWindow 643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 656142a54baae3289f734947c6b5375b12eb0fb722Chris Banespublic class ListPopupWindow implements ShowableListMenu { 663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private static final String TAG = "ListPopupWindow"; 673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private static final boolean DEBUG = false; 683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 7049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * This value controls the length of time that the user 7149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * must leave a pointer down without scrolling to expand 7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the autocomplete dropdown list to cover the IME. 733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private static final int EXPAND_LIST_TIMEOUT = 250; 753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 76ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes private static Method sClipToWindowEnabledMethod; 777ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes private static Method sGetMaxAvailableHeightMethod; 786142a54baae3289f734947c6b5375b12eb0fb722Chris Banes private static Method sSetEpicenterBoundsMethod; 79ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes 80ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes static { 81ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes try { 82ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes sClipToWindowEnabledMethod = PopupWindow.class.getDeclaredMethod( 83ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes "setClipToScreenEnabled", boolean.class); 84ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } catch (NoSuchMethodException e) { 85ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes Log.i(TAG, "Could not find method setClipToScreenEnabled() on PopupWindow. Oh well."); 86ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 877ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes try { 887ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes sGetMaxAvailableHeightMethod = PopupWindow.class.getDeclaredMethod( 897ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes "getMaxAvailableHeight", View.class, int.class, boolean.class); 907ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } catch (NoSuchMethodException e) { 917ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes Log.i(TAG, "Could not find method getMaxAvailableHeight(View, int, boolean)" 927ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes + " on PopupWindow. Oh well."); 937ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } 946142a54baae3289f734947c6b5375b12eb0fb722Chris Banes try { 956142a54baae3289f734947c6b5375b12eb0fb722Chris Banes sSetEpicenterBoundsMethod = PopupWindow.class.getDeclaredMethod( 966142a54baae3289f734947c6b5375b12eb0fb722Chris Banes "setEpicenterBounds", Rect.class); 976142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } catch (NoSuchMethodException e) { 986142a54baae3289f734947c6b5375b12eb0fb722Chris Banes Log.i(TAG, "Could not find method setEpicenterBounds(Rect) on PopupWindow. Oh well."); 996142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } 100ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 101ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes 1023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private Context mContext; 1033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private ListAdapter mAdapter; 1043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private DropDownListView mDropDownList; 1053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int mDropDownHeight = ViewGroup.LayoutParams.WRAP_CONTENT; 1073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int mDropDownWidth = ViewGroup.LayoutParams.WRAP_CONTENT; 1083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int mDropDownHorizontalOffset; 1093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int mDropDownVerticalOffset; 11018864e53490e04739f1063a7ee113549874f87b0Chris Banes private int mDropDownWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; 1113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private boolean mDropDownVerticalOffsetSet; 1126142a54baae3289f734947c6b5375b12eb0fb722Chris Banes private boolean mIsAnimatedFromAnchor = true; 1133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mDropDownGravity = Gravity.NO_GRAVITY; 11549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private boolean mDropDownAlwaysVisible = false; 1173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private boolean mForceIgnoreOutsideTouch = false; 1183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int mListItemExpandMaximum = Integer.MAX_VALUE; 1193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private View mPromptView; 1213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int mPromptPosition = POSITION_PROMPT_ABOVE; 1223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private DataSetObserver mObserver; 1243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private View mDropDownAnchorView; 1263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private Drawable mDropDownListHighlight; 1283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private AdapterView.OnItemClickListener mItemClickListener; 1306142a54baae3289f734947c6b5375b12eb0fb722Chris Banes private OnItemSelectedListener mItemSelectedListener; 1313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private final ResizePopupRunnable mResizePopupRunnable = new ResizePopupRunnable(); 1333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private final PopupTouchInterceptor mTouchInterceptor = new PopupTouchInterceptor(); 1343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private final PopupScrollListener mScrollListener = new PopupScrollListener(); 1353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private final ListSelectorHider mHideSelector = new ListSelectorHider(); 1363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private Runnable mShowDropDownRunnable; 1373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13818864e53490e04739f1063a7ee113549874f87b0Chris Banes private final Handler mHandler; 1393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1406142a54baae3289f734947c6b5375b12eb0fb722Chris Banes private final Rect mTempRect = new Rect(); 1416142a54baae3289f734947c6b5375b12eb0fb722Chris Banes 1426142a54baae3289f734947c6b5375b12eb0fb722Chris Banes /** 1436142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * Optional anchor-relative bounds to be used as the transition epicenter. 1446142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * When {@code null}, the anchor bounds are used as the epicenter. 1456142a54baae3289f734947c6b5375b12eb0fb722Chris Banes */ 1466142a54baae3289f734947c6b5375b12eb0fb722Chris Banes private Rect mEpicenterBounds; 1473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private boolean mModal; 1493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes PopupWindow mPopup; 1513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 1533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * The provided prompt view should appear above list content. 1543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 1553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setPromptPosition(int) 1563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #getPromptPosition() 1573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setPromptView(View) 1583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 1593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int POSITION_PROMPT_ABOVE = 0; 1603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 1623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * The provided prompt view should appear below list content. 1633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 1643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setPromptPosition(int) 1653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #getPromptPosition() 1663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setPromptView(View) 1673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 1683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int POSITION_PROMPT_BELOW = 1; 1693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 17149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Alias for {@link ViewGroup.LayoutParams#MATCH_PARENT}. 17249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If used to specify a popup width, the popup will match the width of the anchor view. 17349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If used to specify a popup height, the popup will fill available space. 1743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 17549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static final int MATCH_PARENT = ViewGroup.LayoutParams.MATCH_PARENT; 1763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 17849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Alias for {@link ViewGroup.LayoutParams#WRAP_CONTENT}. 17949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If used to specify a popup width, the popup will use the width of its content. 1803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 1813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int WRAP_CONTENT = ViewGroup.LayoutParams.WRAP_CONTENT; 1823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 18449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Mode for {@link #setInputMethodMode(int)}: the requirements for the 18549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * input method should be based on the focusability of the popup. That is 18649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * if it is focusable than it needs to work with the input method, else 18749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * it doesn't. 1883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 1893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int INPUT_METHOD_FROM_FOCUSABLE = PopupWindow.INPUT_METHOD_FROM_FOCUSABLE; 1903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 19249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Mode for {@link #setInputMethodMode(int)}: this popup always needs to 19349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * work with an input method, regardless of whether it is focusable. This 19449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * means that it will always be displayed so that the user can also operate 19549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the input method while it is shown. 1963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 1973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int INPUT_METHOD_NEEDED = PopupWindow.INPUT_METHOD_NEEDED; 1983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 1993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Mode for {@link #setInputMethodMode(int)}: this popup never needs to 20149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * work with an input method, regardless of whether it is focusable. This 20249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * means that it will always be displayed to use as much space on the 20349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * screen as needed, regardless of whether this covers the input method. 2043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 2053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public static final int INPUT_METHOD_NOT_NEEDED = PopupWindow.INPUT_METHOD_NOT_NEEDED; 2063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 20849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Create a new, empty popup window capable of displaying items from a ListAdapter. 20949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}. 2103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 2113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param context Context used for contained views. 2123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 2136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public ListPopupWindow(@NonNull Context context) { 214ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns this(context, null, R.attr.listPopupWindowStyle); 2153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Create a new, empty popup window capable of displaying items from a ListAdapter. 21949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}. 2203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 2213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param context Context used for contained views. 22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * @param attrs Attributes from inflating parent views used to style the popup. 2233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 2246142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs) { 225ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns this(context, attrs, R.attr.listPopupWindowStyle); 2263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Create a new, empty popup window capable of displaying items from a ListAdapter. 23049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}. 2313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 23249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param context Context used for contained views. 23349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param attrs Attributes from inflating parent views used to style the popup. 2343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param defStyleAttr Default style attribute to use for popup content. 2353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 2366142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs, 2376142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @AttrRes int defStyleAttr) { 238a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette this(context, attrs, defStyleAttr, 0); 239a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette } 240a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette 241a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette /** 242a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * Create a new, empty popup window capable of displaying items from a ListAdapter. 243a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * Backgrounds should be set using {@link #setBackgroundDrawable(Drawable)}. 244a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * 245a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * @param context Context used for contained views. 246a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * @param attrs Attributes from inflating parent views used to style the popup. 247a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * @param defStyleAttr Style attribute to read for default styling of popup content. 248a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette * @param defStyleRes Style resource ID to use for default styling of popup content. 249a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette */ 2506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public ListPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs, 2516142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { 2523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mContext = context; 25318864e53490e04739f1063a7ee113549874f87b0Chris Banes mHandler = new Handler(context.getMainLooper()); 254ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes 255ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListPopupWindow, 256a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette defStyleAttr, defStyleRes); 257ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes mDropDownHorizontalOffset = a.getDimensionPixelOffset( 258ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes R.styleable.ListPopupWindow_android_dropDownHorizontalOffset, 0); 259ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes mDropDownVerticalOffset = a.getDimensionPixelOffset( 260ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes R.styleable.ListPopupWindow_android_dropDownVerticalOffset, 0); 261ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes if (mDropDownVerticalOffset != 0) { 262ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes mDropDownVerticalOffsetSet = true; 263ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 264ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes a.recycle(); 265ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes 266b2d5231158a58f03b611a8e4065de02938c54e26Chris Banes if (Build.VERSION.SDK_INT >= 11) { 267b2d5231158a58f03b611a8e4065de02938c54e26Chris Banes mPopup = new AppCompatPopupWindow(context, attrs, defStyleAttr, defStyleRes); 268b2d5231158a58f03b611a8e4065de02938c54e26Chris Banes } else { 269b2d5231158a58f03b611a8e4065de02938c54e26Chris Banes mPopup = new AppCompatPopupWindow(context, attrs, defStyleAttr); 270b2d5231158a58f03b611a8e4065de02938c54e26Chris Banes } 2713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); 272ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns } 2733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 27549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Sets the adapter that provides the data and the views to represent the data 27649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * in this popup window. 2773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 2783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param adapter The adapter to use to create this window's content. 2793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 2806142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setAdapter(@Nullable ListAdapter adapter) { 2813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mObserver == null) { 2823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mObserver = new PopupDataSetObserver(); 2833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else if (mAdapter != null) { 2843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mAdapter.unregisterDataSetObserver(mObserver); 2853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mAdapter = adapter; 2873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mAdapter != null) { 2883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani adapter.registerDataSetObserver(mObserver); 2893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mDropDownList != null) { 2923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setAdapter(mAdapter); 2933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 2953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 2963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 29749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set where the optional prompt view should appear. The default is 29849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #POSITION_PROMPT_ABOVE}. 2993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param position A position constant declaring where the prompt should be displayed. 30149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 3023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #POSITION_PROMPT_ABOVE 3033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #POSITION_PROMPT_BELOW 3043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setPromptPosition(int position) { 3063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPromptPosition = position; 3073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return Where the optional prompt view should appear. 31149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 3123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #POSITION_PROMPT_ABOVE 3133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #POSITION_PROMPT_BELOW 3143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getPromptPosition() { 3163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPromptPosition; 3173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set whether this window should be modal when shown. 3213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 32249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>If a popup window is modal, it will receive all touch and key input. 32349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * If the user touches outside the popup window's content area the popup window 32449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * will be dismissed. 3253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param modal {@code true} if the popup window should be modal, {@code false} otherwise. 3273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setModal(boolean modal) { 329a2c72b87007d10202c25e78e904938f770c6337dChris Banes mModal = modal; 3303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setFocusable(modal); 3313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Returns whether the popup window will be modal when shown. 3353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return {@code true} if the popup window will be modal, {@code false} otherwise. 3373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean isModal() { 3393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mModal; 3403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Forces outside touches to be ignored. Normally if {@link #isDropDownAlwaysVisible()} is 34449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * false, we allow outside touch to dismiss the dropdown. If this is set to true, then we 34549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * ignore outside touch even when the drop down is not set to always visible. 3463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @hide Used only by AutoCompleteTextView to handle some internal special cases. 3483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setForceIgnoreOutsideTouch(boolean forceIgnoreOutsideTouch) { 3503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mForceIgnoreOutsideTouch = forceIgnoreOutsideTouch; 3513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets whether the drop-down should remain visible under certain conditions. 3553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 35649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * The drop-down will occupy the entire screen below {@link #getAnchorView} regardless 35749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * of the size or content of the list. {@link #getBackground()} will fill any space 35849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * that is not used by the list. 3593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param dropDownAlwaysVisible Whether to keep the drop-down visible. 36149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 3623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @hide Only used by AutoCompleteTextView under special conditions. 3633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setDropDownAlwaysVisible(boolean dropDownAlwaysVisible) { 3653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownAlwaysVisible = dropDownAlwaysVisible; 3663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return Whether the drop-down is visible under special conditions. 37049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 3713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @hide Only used by AutoCompleteTextView under special conditions. 3723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean isDropDownAlwaysVisible() { 3743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownAlwaysVisible; 3753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets the operating mode for the soft input area. 3793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 38049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param mode The desired mode, see 38149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link android.view.WindowManager.LayoutParams#softInputMode} 38249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * for the full list 38349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 3843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see android.view.WindowManager.LayoutParams#softInputMode 3853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #getSoftInputMode() 3863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setSoftInputMode(int mode) { 3883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setSoftInputMode(mode); 3893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 3903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 3913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 3923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Returns the current value in {@link #setSoftInputMode(int)}. 3933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 3943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setSoftInputMode(int) 3953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see android.view.WindowManager.LayoutParams#softInputMode 3963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 3973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getSoftInputMode() { 3983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.getSoftInputMode(); 3993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets a drawable to use as the list item selector. 4033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param selector List selector drawable to use in the popup. 4053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setListSelector(Drawable selector) { 4073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownListHighlight = selector; 4083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The background drawable for the popup window. 4123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @Nullable Drawable getBackground() { 4143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.getBackground(); 4153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets a drawable to be the background for the popup window. 4193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param d A drawable to set as the background. 4213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4226142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setBackgroundDrawable(@Nullable Drawable d) { 4233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setBackgroundDrawable(d); 4243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set an animation style to use when the popup window is shown or dismissed. 4283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param animationStyle Animation style to use. 4303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4316142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setAnimationStyle(@StyleRes int animationStyle) { 4323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setAnimationStyle(animationStyle); 4333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4366142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * Returns the animation style that will be used when the popup window is 4376142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * shown or dismissed. 4383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return Animation style that will be used. 4403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4416142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @StyleRes int getAnimationStyle() { 4423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.getAnimationStyle(); 4433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Returns the view that will be used to anchor this popup. 4473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The popup's anchor view 4493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4506142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @Nullable View getAnchorView() { 4513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownAnchorView; 4523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4556142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * Sets the popup's anchor view. This popup will always be positioned relative to 4566142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * the anchor view when shown. 4573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param anchor The view to use as an anchor. 4593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4606142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setAnchorView(@Nullable View anchor) { 4613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownAnchorView = anchor; 4623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The horizontal offset of the popup from its anchor in pixels. 4663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getHorizontalOffset() { 4683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownHorizontalOffset; 4693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set the horizontal offset of this popup from its anchor view in pixels. 4733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param offset The horizontal offset of the popup from its anchor. 4753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setHorizontalOffset(int offset) { 4773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownHorizontalOffset = offset; 4783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The vertical offset of the popup from its anchor in pixels. 4823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getVerticalOffset() { 4843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!mDropDownVerticalOffsetSet) { 4853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return 0; 4863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownVerticalOffset; 4883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 4903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 4913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set the vertical offset of this popup from its anchor view in pixels. 4923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 4933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param offset The vertical offset of the popup from its anchor. 4943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 4953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setVerticalOffset(int offset) { 4963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownVerticalOffset = offset; 4973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownVerticalOffsetSet = true; 4983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 4993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 5016142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * Specifies the anchor-relative bounds of the popup's transition 5026142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * epicenter. 5036142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * 5046142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * @param bounds anchor-relative bounds 5056142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * @hide 5066142a54baae3289f734947c6b5375b12eb0fb722Chris Banes */ 5076142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setEpicenterBounds(Rect bounds) { 5086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes mEpicenterBounds = bounds; 5096142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } 5106142a54baae3289f734947c6b5375b12eb0fb722Chris Banes 5116142a54baae3289f734947c6b5375b12eb0fb722Chris Banes /** 51249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set the gravity of the dropdown list. This is commonly used to 51349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * set gravity to START or END for alignment with the anchor. 51449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 51549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param gravity Gravity value to use 51649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 51749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setDropDownGravity(int gravity) { 51849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDropDownGravity = gravity; 51949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 52049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 52149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 5223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The width of the popup window in pixels. 5233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getWidth() { 5253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownWidth; 5263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 52949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Sets the width of the popup window in pixels. Can also be {@link #MATCH_PARENT} 53049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * or {@link #WRAP_CONTENT}. 5313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 5323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param width Width of the popup window. 5333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setWidth(int width) { 5353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownWidth = width; 5363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 53949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Sets the width of the popup window by the size of its content. The final width may be 54049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * larger to accommodate styled window dressing. 5413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 5423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param width Desired width of content in pixels. 5433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setContentWidth(int width) { 5453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani Drawable popupBackground = mPopup.getBackground(); 5463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (popupBackground != null) { 5473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani popupBackground.getPadding(mTempRect); 5483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownWidth = mTempRect.left + mTempRect.right + width; 5493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 5503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani setWidth(width); 5513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 5553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The height of the popup window in pixels. 5563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getHeight() { 5583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownHeight; 5593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 56249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}. 5633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 5643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param height Height of the popup window. 5653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setHeight(int height) { 5673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownHeight = height; 5683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 57118864e53490e04739f1063a7ee113549874f87b0Chris Banes * Set the layout type for this popup window. 57218864e53490e04739f1063a7ee113549874f87b0Chris Banes * <p> 57318864e53490e04739f1063a7ee113549874f87b0Chris Banes * See {@link WindowManager.LayoutParams#type} for possible values. 57418864e53490e04739f1063a7ee113549874f87b0Chris Banes * 57518864e53490e04739f1063a7ee113549874f87b0Chris Banes * @param layoutType Layout type for this window. 57618864e53490e04739f1063a7ee113549874f87b0Chris Banes * 57718864e53490e04739f1063a7ee113549874f87b0Chris Banes * @see WindowManager.LayoutParams#type 57818864e53490e04739f1063a7ee113549874f87b0Chris Banes */ 57918864e53490e04739f1063a7ee113549874f87b0Chris Banes public void setWindowLayoutType(int layoutType) { 58018864e53490e04739f1063a7ee113549874f87b0Chris Banes mDropDownWindowLayoutType = layoutType; 58118864e53490e04739f1063a7ee113549874f87b0Chris Banes } 58218864e53490e04739f1063a7ee113549874f87b0Chris Banes 58318864e53490e04739f1063a7ee113549874f87b0Chris Banes /** 5843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets a listener to receive events when a list item is clicked. 5853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 5863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param clickListener Listener to register 58749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 5883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see ListView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener) 5893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 5906142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setOnItemClickListener(@Nullable AdapterView.OnItemClickListener clickListener) { 5913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mItemClickListener = clickListener; 5923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 5933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 5943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 5953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Sets a listener to receive events when a list item is selected. 5963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 5973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param selectedListener Listener to register. 59849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 5996142a54baae3289f734947c6b5375b12eb0fb722Chris Banes * @see ListView#setOnItemSelectedListener(OnItemSelectedListener) 6003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 6016142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setOnItemSelectedListener(@Nullable OnItemSelectedListener selectedListener) { 6023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mItemSelectedListener = selectedListener; 6033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 6063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set a view to act as a user prompt for this popup window. Where the prompt view will appear 6073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * is controlled by {@link #setPromptPosition(int)}. 6083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 6093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param prompt View to use as an informational prompt. 6103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 6116142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setPromptView(@Nullable View prompt) { 6123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani boolean showing = isShowing(); 6133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (showing) { 6143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani removePromptView(); 6153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPromptView = prompt; 6173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (showing) { 6183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 6193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 6233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Post a {@link #show()} call to the UI thread. 6243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 6253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void postShow() { 6263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.post(mShowDropDownRunnable); 6273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 63049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Show the popup list. If the list is already showing, this method 63149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * will recalculate the popup's size and position. 6323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 6336142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @Override 6343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void show() { 6353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int height = buildDropDown(); 6363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6376142a54baae3289f734947c6b5375b12eb0fb722Chris Banes final boolean noInputMethod = isInputMethodNotNeeded(); 63818864e53490e04739f1063a7ee113549874f87b0Chris Banes PopupWindowCompat.setWindowLayoutType(mPopup, mDropDownWindowLayoutType); 6393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mPopup.isShowing()) { 64118864e53490e04739f1063a7ee113549874f87b0Chris Banes final int widthSpec; 64249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { 6433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // The call to PopupWindow's update method below can accept -1 for any 6443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // value you do not want to update. 6453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani widthSpec = -1; 6463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { 6473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani widthSpec = getAnchorView().getWidth(); 6483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 6493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani widthSpec = mDropDownWidth; 6503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 65218864e53490e04739f1063a7ee113549874f87b0Chris Banes final int heightSpec; 65349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { 6543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // The call to PopupWindow's update method below can accept -1 for any 6553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // value you do not want to update. 65649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.MATCH_PARENT; 6573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (noInputMethod) { 65818864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? 65918864e53490e04739f1063a7ee113549874f87b0Chris Banes ViewGroup.LayoutParams.MATCH_PARENT : 0); 66018864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setHeight(0); 6613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 66218864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setWidth(mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT ? 66318864e53490e04739f1063a7ee113549874f87b0Chris Banes ViewGroup.LayoutParams.MATCH_PARENT : 0); 66418864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setHeight(ViewGroup.LayoutParams.MATCH_PARENT); 6653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { 6673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani heightSpec = height; 6683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 6693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani heightSpec = mDropDownHeight; 6703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible); 6733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 6743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.update(getAnchorView(), mDropDownHorizontalOffset, 67518864e53490e04739f1063a7ee113549874f87b0Chris Banes mDropDownVerticalOffset, (widthSpec < 0)? -1 : widthSpec, 67618864e53490e04739f1063a7ee113549874f87b0Chris Banes (heightSpec < 0)? -1 : heightSpec); 6773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 67818864e53490e04739f1063a7ee113549874f87b0Chris Banes final int widthSpec; 67949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) { 68049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes widthSpec = ViewGroup.LayoutParams.MATCH_PARENT; 6813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 6823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) { 68318864e53490e04739f1063a7ee113549874f87b0Chris Banes widthSpec = getAnchorView().getWidth(); 6843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 68518864e53490e04739f1063a7ee113549874f87b0Chris Banes widthSpec = mDropDownWidth; 6863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 68918864e53490e04739f1063a7ee113549874f87b0Chris Banes final int heightSpec; 69049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { 69149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes heightSpec = ViewGroup.LayoutParams.MATCH_PARENT; 6923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 6933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { 69418864e53490e04739f1063a7ee113549874f87b0Chris Banes heightSpec = height; 6953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 69618864e53490e04739f1063a7ee113549874f87b0Chris Banes heightSpec = mDropDownHeight; 6973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 6993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 70018864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setWidth(widthSpec); 70118864e53490e04739f1063a7ee113549874f87b0Chris Banes mPopup.setHeight(heightSpec); 702ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes setPopupClipToScreenEnabled(true); 7033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // use outside touchable to dismiss drop down when touching outside of it, so 7053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // only set this if the dropdown is not always visible 7063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible); 7073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setTouchInterceptor(mTouchInterceptor); 7086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes if (sSetEpicenterBoundsMethod != null) { 7096142a54baae3289f734947c6b5375b12eb0fb722Chris Banes try { 7106142a54baae3289f734947c6b5375b12eb0fb722Chris Banes sSetEpicenterBoundsMethod.invoke(mPopup, mEpicenterBounds); 7116142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } catch (Exception e) { 7126142a54baae3289f734947c6b5375b12eb0fb722Chris Banes Log.e(TAG, "Could not invoke setEpicenterBounds on PopupWindow", e); 7136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } 7146142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } 71549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes PopupWindowCompat.showAsDropDown(mPopup, getAnchorView(), mDropDownHorizontalOffset, 71649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDropDownVerticalOffset, mDropDownGravity); 7173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setSelection(ListView.INVALID_POSITION); 7183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!mModal || mDropDownList.isInTouchMode()) { 7203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani clearListSelection(); 7213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!mModal) { 7233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.post(mHideSelector); 7243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 7293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Dismiss the popup window. 7303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 7316142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @Override 7323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void dismiss() { 7333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.dismiss(); 7343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani removePromptView(); 7353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setContentView(null); 7363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList = null; 7373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.removeCallbacks(mResizePopupRunnable); 7383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 7413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Set a listener to receive a callback when the popup is dismissed. 7423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 7433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param listener Listener that will be notified when the popup is dismissed. 7443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 7456142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public void setOnDismissListener(@Nullable PopupWindow.OnDismissListener listener) { 7463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setOnDismissListener(listener); 7473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private void removePromptView() { 7503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mPromptView != null) { 7513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final ViewParent parent = mPromptView.getParent(); 7523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (parent instanceof ViewGroup) { 7533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final ViewGroup group = (ViewGroup) parent; 7543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani group.removeView(mPromptView); 7553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 76049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Control how the popup operates with an input method: one of 76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #INPUT_METHOD_FROM_FOCUSABLE}, {@link #INPUT_METHOD_NEEDED}, 76249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * or {@link #INPUT_METHOD_NOT_NEEDED}. 7633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 76449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>If the popup is showing, calling this method will take effect only 76549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the next time the popup is shown or through a manual call to the {@link #show()} 76649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * method.</p> 7673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 7683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #getInputMethodMode() 7693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #show() 7703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 7713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setInputMethodMode(int mode) { 7723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setInputMethodMode(mode); 7733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 7763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Return the current value in {@link #setInputMethodMode(int)}. 7773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 7783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setInputMethodMode(int) 7793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 7803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getInputMethodMode() { 7813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.getInputMethodMode(); 7823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 7833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 7843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 78549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Set the selected position of the list. 78649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Only valid when {@link #isShowing()} == {@code true}. 7873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 7883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param position List position to set as selected. 7893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 7903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void setSelection(int position) { 7913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani DropDownListView list = mDropDownList; 7923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (isShowing() && list != null) { 7936142a54baae3289f734947c6b5375b12eb0fb722Chris Banes list.setListSelectionHidden(false); 7943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani list.setSelection(position); 79549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 79649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (Build.VERSION.SDK_INT >= 11) { 79749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (list.getChoiceMode() != ListView.CHOICE_MODE_NONE) { 79849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes list.setItemChecked(position, true); 79949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 8003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 80549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Clear any current list selection. 80649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Only valid when {@link #isShowing()} == {@code true}. 8073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void clearListSelection() { 8093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final DropDownListView list = mDropDownList; 8103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (list != null) { 8113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // WARNING: Please read the comment where mListSelectionHidden is declared 8126142a54baae3289f734947c6b5375b12eb0fb722Chris Banes list.setListSelectionHidden(true); 8133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani //list.hideSelector(); 8143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani list.requestLayout(); 8153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 8193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return {@code true} if the popup is currently showing, {@code false} otherwise. 8203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8216142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @Override 8223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean isShowing() { 8233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.isShowing(); 8243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 82749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return {@code true} if this popup is configured to assume the user does not need 82849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to interact with the IME while it is showing, {@code false} otherwise. 8293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean isInputMethodNotNeeded() { 8313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mPopup.getInputMethodMode() == INPUT_METHOD_NOT_NEEDED; 8323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 8353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * Perform an item click operation on the specified list adapter position. 8363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 8373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param position Adapter position for performing the click 83849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if the click action could be performed, false if not. 83949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * (e.g. if the popup was not showing, this method would return false.) 8403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean performItemClick(int position) { 8423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (isShowing()) { 8433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mItemClickListener != null) { 8443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final DropDownListView list = mDropDownList; 8453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final View child = list.getChildAt(position - list.getFirstVisiblePosition()); 8463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final ListAdapter adapter = list.getAdapter(); 8473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mItemClickListener.onItemClick(list, child, position, adapter.getItemId(position)); 8483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return true; 8503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return false; 8523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 8553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return The currently selected item or null if the popup is not showing. 8563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8576142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @Nullable Object getSelectedItem() { 8583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!isShowing()) { 8593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return null; 8603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownList.getSelectedItem(); 8623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 86549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return The position of the currently selected item or {@link ListView#INVALID_POSITION} 86649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * if {@link #isShowing()} == {@code false}. 86749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 8683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see ListView#getSelectedItemPosition() 8693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public int getSelectedItemPosition() { 8713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!isShowing()) { 8723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return ListView.INVALID_POSITION; 8733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownList.getSelectedItemPosition(); 8753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 87849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return The ID of the currently selected item or {@link ListView#INVALID_ROW_ID} 87949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * if {@link #isShowing()} == {@code false}. 88049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 8813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see ListView#getSelectedItemId() 8823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public long getSelectedItemId() { 8843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!isShowing()) { 8853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return ListView.INVALID_ROW_ID; 8863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownList.getSelectedItemId(); 8883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 8893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 8903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 89149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return The View for the currently selected item or null if 89249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * {@link #isShowing()} == {@code false}. 89349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 8943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see ListView#getSelectedView() 8953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 8966142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @Nullable View getSelectedView() { 8973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!isShowing()) { 8983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return null; 8993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownList.getSelectedView(); 9013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 90449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return The {@link ListView} displayed within the popup window. 90549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Only valid when {@link #isShowing()} == {@code true}. 9063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 9076142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @Override 9086142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public @Nullable ListView getListView() { 9093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return mDropDownList; 9103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9126142a54baae3289f734947c6b5375b12eb0fb722Chris Banes @NonNull DropDownListView createDropDownListView(Context context, boolean hijackFocus) { 9136142a54baae3289f734947c6b5375b12eb0fb722Chris Banes return new DropDownListView(context, hijackFocus); 9146142a54baae3289f734947c6b5375b12eb0fb722Chris Banes } 9156142a54baae3289f734947c6b5375b12eb0fb722Chris Banes 9163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 91749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * The maximum number of list items that can be visible and still have 91849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the list expand when touched. 9193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 9203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param max Max number of items that can be visible and still allow the list to expand. 9213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 9223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani void setListItemExpandMax(int max) { 9233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mListItemExpandMaximum = max; 9243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 92749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Filter key down events. By forwarding key down events to this function, 92849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * views using non-modal ListPopupWindow can have it handle key selection of items. 9293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 9303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param keyCode keyCode param passed to the host view's onKeyDown 93149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param event event param passed to the host view's onKeyDown 9323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return true if the event was handled, false if it was ignored. 93349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 9343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setModal(boolean) 9353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 9366142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) { 9373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // when the drop down is shown, we drive it directly 9383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (isShowing()) { 9393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // the key events are forwarded to the list in the drop down view 9403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // note that ListView handles space but we don't want that to happen 9413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // also if selection is not currently in the drop down, then don't 9423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // let center or enter presses go there since that would cause it 9433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // to select one of its items 9443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (keyCode != KeyEvent.KEYCODE_SPACE 9453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani && (mDropDownList.getSelectedItemPosition() >= 0 94649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes || !isConfirmKey(keyCode))) { 9473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int curIndex = mDropDownList.getSelectedItemPosition(); 9483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani boolean consumed; 9493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final boolean below = !mPopup.isAboveAnchor(); 9513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final ListAdapter adapter = mAdapter; 9533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9543565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani boolean allEnabled; 9553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int firstItem = Integer.MAX_VALUE; 9563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int lastItem = Integer.MIN_VALUE; 9573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (adapter != null) { 9593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani allEnabled = adapter.areAllItemsEnabled(); 9603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani firstItem = allEnabled ? 0 : 961ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns mDropDownList.lookForSelectablePosition(0, true); 9623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani lastItem = allEnabled ? adapter.getCount() - 1 : 963ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns mDropDownList.lookForSelectablePosition(adapter.getCount() - 1, false); 9643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if ((below && keyCode == KeyEvent.KEYCODE_DPAD_UP && curIndex <= firstItem) || 9673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani (!below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN && curIndex >= lastItem)) { 9683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // When the selection is at the top, we block the key 9693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // event to prevent focus from moving. 9703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani clearListSelection(); 9713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); 9723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 9733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return true; 9743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 9753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // WARNING: Please read the comment where mListSelectionHidden 9763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // is declared 9776142a54baae3289f734947c6b5375b12eb0fb722Chris Banes mDropDownList.setListSelectionHidden(false); 9783565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 9793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani consumed = mDropDownList.onKeyDown(keyCode, event); 98149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (DEBUG) Log.v(TAG, "Key down: code=" + keyCode + " list consumed=" + consumed); 9823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (consumed) { 9843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // If it handled the key event, then the user is 9853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // navigating in the list, so we should put it in front. 9863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); 9873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // Here's a little trick we need to do to make sure that 9883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // the list view is actually showing its focus indicator, 9893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // by ensuring it has focus and getting its window out 9903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // of touch mode. 9913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.requestFocusFromTouch(); 9923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 9933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 9943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani switch (keyCode) { 9953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // avoid passing the focus from the text view to the 9963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // next component 9973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case KeyEvent.KEYCODE_ENTER: 9983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case KeyEvent.KEYCODE_DPAD_CENTER: 9993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case KeyEvent.KEYCODE_DPAD_DOWN: 10003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case KeyEvent.KEYCODE_DPAD_UP: 10013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return true; 10023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 10043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (below && keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 10053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // when the selection is at the bottom, we block the 10063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // event to avoid going to the next focusable widget 10073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (curIndex == lastItem) { 10083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return true; 10093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else if (!below && keyCode == KeyEvent.KEYCODE_DPAD_UP && 10113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani curIndex == firstItem) { 10123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return true; 10133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 10183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return false; 10193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 10213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 102249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Filter key down events. By forwarding key up events to this function, 102349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * views using non-modal ListPopupWindow can have it handle key selection of items. 10243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 10253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @param keyCode keyCode param passed to the host view's onKeyUp 102649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param event event param passed to the host view's onKeyUp 10273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return true if the event was handled, false if it was ignored. 102849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 10293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @see #setModal(boolean) 10303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 10316142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) { 10323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) { 10333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani boolean consumed = mDropDownList.onKeyUp(keyCode, event); 103449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (consumed && isConfirmKey(keyCode)) { 103549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // if the list accepts the key events and the key event was a click, the text view 103649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // gets the selected item from the drop down as its content 103749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes dismiss(); 10383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return consumed; 10403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return false; 10423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 10433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 10443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 104549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Filter pre-IME key events. By forwarding {@link View#onKeyPreIme(int, KeyEvent)} 104649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * events to this function, views using ListPopupWindow can have it dismiss the popup 104749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * when the back key is pressed. 104849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 104949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param keyCode keyCode param passed to the host view's onKeyPreIme 105049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param event event param passed to the host view's onKeyPreIme 105149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if the event was handled, false if it was ignored. 105249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 105349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setModal(boolean) 105449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 10556142a54baae3289f734947c6b5375b12eb0fb722Chris Banes public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) { 105649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (keyCode == KeyEvent.KEYCODE_BACK && isShowing()) { 105749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // special case for the back key, we do not even try to send it 105849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // to the drop down list but instead, consume it immediately 105949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final View anchorView = mDropDownAnchorView; 106049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { 106149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState(); 106249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (state != null) { 106349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes state.startTracking(event, this); 106449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 106549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return true; 106649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (event.getAction() == KeyEvent.ACTION_UP) { 106749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState(); 106849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (state != null) { 106949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes state.handleUpEvent(event); 107049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 107149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (event.isTracking() && !event.isCanceled()) { 107249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes dismiss(); 107349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return true; 107449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 107549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 107649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 107749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 107849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 107949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 108049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 108149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns an {@link OnTouchListener} that can be added to the source view 108249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * to implement drag-to-open behavior. Generally, the source view should be 108349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the same view that was passed to {@link #setAnchorView}. 108449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p> 108549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * When the listener is set on a view, touching that view and dragging 108649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * outside of its bounds will open the popup window. Lifting will select the 108749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * currently touched list item. 108849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p> 108949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Example usage: 109049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <pre> 109149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * ListPopupWindow myPopup = new ListPopupWindow(context); 109249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * myPopup.setAnchor(myAnchor); 109349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * OnTouchListener dragListener = myPopup.createDragToOpenListener(myAnchor); 109449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * myAnchor.setOnTouchListener(dragListener); 109549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * </pre> 109649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 109749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param src the view on which the resulting listener will be set 109849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return a touch listener that controls drag-to-open behavior 109949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 110049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public OnTouchListener createDragToOpenListener(View src) { 110149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return new ForwardingListener(src) { 110249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 110349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public ListPopupWindow getPopup() { 110449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return ListPopupWindow.this; 110549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 110649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes }; 110749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 110849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 110949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 111049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Builds the popup window's content and returns the height the popup 111149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * should have. Returns -1 when the content already exists.</p> 11123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * 11133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * @return the content's height or -1 if content already exists 11143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 11153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private int buildDropDown() { 11163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani ViewGroup dropDownView; 11173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani int otherHeights = 0; 11183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mDropDownList == null) { 11203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani Context context = mContext; 11213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani /** 11233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * This Runnable exists for the sole purpose of checking if the view layout has got 11243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * completed and if so call showDropDown to display the drop down. This is used to show 11253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * the drop down as soon as possible after user opens up the search dialog, without 11263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani * waiting for the normal UI pipeline to do it's job which is slower than this method. 11273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani */ 11283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mShowDropDownRunnable = new Runnable() { 11293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void run() { 11303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // View layout should be all done before displaying the drop down. 11313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani View view = getAnchorView(); 11323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (view != null && view.getWindowToken() != null) { 11333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 11343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani }; 11373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11386142a54baae3289f734947c6b5375b12eb0fb722Chris Banes mDropDownList = createDropDownListView(context, !mModal); 11393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mDropDownListHighlight != null) { 11403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setSelector(mDropDownListHighlight); 11413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setAdapter(mAdapter); 11433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setOnItemClickListener(mItemClickListener); 11443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setFocusable(true); 11453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setFocusableInTouchMode(true); 11466142a54baae3289f734947c6b5375b12eb0fb722Chris Banes mDropDownList.setOnItemSelectedListener(new OnItemSelectedListener() { 11473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onItemSelected(AdapterView<?> parent, View view, 114820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int position, long id) { 11493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (position != -1) { 11513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani DropDownListView dropDownList = mDropDownList; 11523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11533565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (dropDownList != null) { 11546142a54baae3289f734947c6b5375b12eb0fb722Chris Banes dropDownList.setListSelectionHidden(false); 11553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onNothingSelected(AdapterView<?> parent) { 11603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani }); 11623565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setOnScrollListener(mScrollListener); 11633565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (mItemSelectedListener != null) { 11653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownList.setOnItemSelectedListener(mItemSelectedListener); 11663565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11683565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani dropDownView = mDropDownList; 11693565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani View hintView = mPromptView; 11713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (hintView != null) { 11723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // if a hint has been specified, we accomodate more space for it and 11733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // add a text view in the drop down menu, at the bottom of the list 11743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani LinearLayout hintContainer = new LinearLayout(context); 11753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintContainer.setOrientation(LinearLayout.VERTICAL); 11763565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11773565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams( 117849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f 11793565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani ); 11803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11813565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani switch (mPromptPosition) { 11823565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case POSITION_PROMPT_BELOW: 11833565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintContainer.addView(dropDownView, hintParams); 11843565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintContainer.addView(hintView); 11853565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 11863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case POSITION_PROMPT_ABOVE: 11883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintContainer.addView(hintView); 11893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintContainer.addView(dropDownView, hintParams); 11903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 11913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 11923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani default: 11933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani Log.e(TAG, "Invalid hint position " + mPromptPosition); 11943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 11953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 11963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 119718864e53490e04739f1063a7ee113549874f87b0Chris Banes // Measure the hint's height to find how much more vertical 119818864e53490e04739f1063a7ee113549874f87b0Chris Banes // space we need to add to the drop down's height. 119918864e53490e04739f1063a7ee113549874f87b0Chris Banes final int widthSize; 120018864e53490e04739f1063a7ee113549874f87b0Chris Banes final int widthMode; 120118864e53490e04739f1063a7ee113549874f87b0Chris Banes if (mDropDownWidth >= 0) { 120218864e53490e04739f1063a7ee113549874f87b0Chris Banes widthMode = MeasureSpec.AT_MOST; 120318864e53490e04739f1063a7ee113549874f87b0Chris Banes widthSize = mDropDownWidth; 120418864e53490e04739f1063a7ee113549874f87b0Chris Banes } else { 120518864e53490e04739f1063a7ee113549874f87b0Chris Banes widthMode = MeasureSpec.UNSPECIFIED; 120618864e53490e04739f1063a7ee113549874f87b0Chris Banes widthSize = 0; 120718864e53490e04739f1063a7ee113549874f87b0Chris Banes } 120818864e53490e04739f1063a7ee113549874f87b0Chris Banes final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); 120918864e53490e04739f1063a7ee113549874f87b0Chris Banes final int heightSpec = MeasureSpec.UNSPECIFIED; 12103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintView.measure(widthSpec, heightSpec); 12113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams(); 12133565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin 12143565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani + hintParams.bottomMargin; 12153565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani dropDownView = hintContainer; 12173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setContentView(dropDownView); 12203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 12213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani dropDownView = (ViewGroup) mPopup.getContentView(); 12223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final View view = mPromptView; 12233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (view != null) { 12243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani LinearLayout.LayoutParams hintParams = 12253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani (LinearLayout.LayoutParams) view.getLayoutParams(); 12263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani otherHeights = view.getMeasuredHeight() + hintParams.topMargin 12273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani + hintParams.bottomMargin; 12283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // getMaxAvailableHeight() subtracts the padding, so we put it back 123276ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette // to get the available height for the whole window. 123376ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette final int padding; 123476ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette final Drawable background = mPopup.getBackground(); 12353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (background != null) { 12363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani background.getPadding(mTempRect); 12373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani padding = mTempRect.top + mTempRect.bottom; 12383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 123976ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette // If we don't have an explicit vertical offset, determine one from 124076ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette // the window background so that content will line up. 12413565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (!mDropDownVerticalOffsetSet) { 12423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mDropDownVerticalOffset = -mTempRect.top; 12433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else { 12453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mTempRect.setEmpty(); 124676ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette padding = 0; 12473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // Max height available on the screen for a popup. 12507ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes final boolean ignoreBottomDecorations = 12513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; 12527ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes final int maxHeight = getMaxAvailableHeight(getAnchorView(), mDropDownVerticalOffset, 12537ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes ignoreBottomDecorations); 1254a2c72b87007d10202c25e78e904938f770c6337dChris Banes if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { 12553565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return maxHeight + padding; 12563565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12573565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12583565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final int childWidthSpec; 12593565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani switch (mDropDownWidth) { 12603565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani case ViewGroup.LayoutParams.WRAP_CONTENT: 12613565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani childWidthSpec = MeasureSpec.makeMeasureSpec( 126276ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette mContext.getResources().getDisplayMetrics().widthPixels 126376ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette - (mTempRect.left + mTempRect.right), 12643565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani MeasureSpec.AT_MOST); 12653565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 1266a2c72b87007d10202c25e78e904938f770c6337dChris Banes case ViewGroup.LayoutParams.MATCH_PARENT: 12673565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani childWidthSpec = MeasureSpec.makeMeasureSpec( 126876ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette mContext.getResources().getDisplayMetrics().widthPixels 126976ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette - (mTempRect.left + mTempRect.right), 12703565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani MeasureSpec.EXACTLY); 12713565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 12723565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani default: 12733565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY); 12743565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani break; 12753565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 1276ba2e44b17a9ed3d39d05b52f9764165e063f5386Trevor Johns 127776ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette // Add padding only if the list has items in it, that way we don't show 127876ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette // the popup if it is not needed. 127979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes final int listContent = mDropDownList.measureHeightOfChildrenCompat(childWidthSpec, 12803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 0, DropDownListView.NO_POSITION, maxHeight - otherHeights, -1); 128176ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette if (listContent > 0) { 128276ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette final int listPadding = mDropDownList.getPaddingTop() 128376ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette + mDropDownList.getPaddingBottom(); 128476ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette otherHeights += padding + listPadding; 128576ecafcac7f7810de047f87931d58c04a8a86dc1Alan Viverette } 12863565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12873565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return listContent + otherHeights; 12883565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12893565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12903565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private class PopupDataSetObserver extends DataSetObserver { 12913565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani @Override 12923565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onChanged() { 12933565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (isShowing()) { 12943565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani // Resize the popup to fit new content 12953565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 12963565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12973565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 12983565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 12993565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani @Override 13003565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onInvalidated() { 13013565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani dismiss(); 13023565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13033565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13043565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13053565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private class ListSelectorHider implements Runnable { 13063565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void run() { 13073565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani clearListSelection(); 13083565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13093565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13103565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13113565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private class ResizePopupRunnable implements Runnable { 13123565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void run() { 131318864e53490e04739f1063a7ee113549874f87b0Chris Banes if (mDropDownList != null && ViewCompat.isAttachedToWindow(mDropDownList) 131418864e53490e04739f1063a7ee113549874f87b0Chris Banes && mDropDownList.getCount() > mDropDownList.getChildCount() 131518864e53490e04739f1063a7ee113549874f87b0Chris Banes && mDropDownList.getChildCount() <= mListItemExpandMaximum) { 13163565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); 13173565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani show(); 13183565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13193565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13203565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13213565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13223565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private class PopupTouchInterceptor implements OnTouchListener { 13233565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public boolean onTouch(View v, MotionEvent event) { 13243565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final int action = event.getAction(); 13253565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final int x = (int) event.getX(); 13263565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani final int y = (int) event.getY(); 13273565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13283565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (action == MotionEvent.ACTION_DOWN && 13293565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mPopup != null && mPopup.isShowing() && 13303565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani (x >= 0 && x < mPopup.getWidth() && y >= 0 && y < mPopup.getHeight())) { 13313565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.postDelayed(mResizePopupRunnable, EXPAND_LIST_TIMEOUT); 13323565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } else if (action == MotionEvent.ACTION_UP) { 13333565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.removeCallbacks(mResizePopupRunnable); 13343565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13353565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani return false; 13363565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13373565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13383565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13393565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani private class PopupScrollListener implements ListView.OnScrollListener { 13403565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 134120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int totalItemCount) { 13423565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13433565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13443565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani 13453565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani public void onScrollStateChanged(AbsListView view, int scrollState) { 13463565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani if (scrollState == SCROLL_STATE_TOUCH_SCROLL && 13473565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani !isInputMethodNotNeeded() && mPopup.getContentView() != null) { 13483565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mHandler.removeCallbacks(mResizePopupRunnable); 13493565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani mResizePopupRunnable.run(); 13503565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13513565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 13523565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani } 135349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 135449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private static boolean isConfirmKey(int keyCode) { 135549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_DPAD_CENTER; 135649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 135749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 1358ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes private void setPopupClipToScreenEnabled(boolean clip) { 1359ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes if (sClipToWindowEnabledMethod != null) { 1360ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes try { 1361ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes sClipToWindowEnabledMethod.invoke(mPopup, clip); 1362ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } catch (Exception e) { 1363ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes Log.i(TAG, "Could not call setClipToScreenEnabled() on PopupWindow. Oh well."); 1364ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 1365ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 1366ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes } 1367ac00a989afc2f1c559fc33174f481a0a0ef5b3d8Chris Banes 13687ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes private int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) { 13697ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes if (sGetMaxAvailableHeightMethod != null) { 13707ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes try { 13717ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes return (int) sGetMaxAvailableHeightMethod.invoke(mPopup, anchor, yOffset, 13727ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes ignoreBottomDecorations); 13737ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } catch (Exception e) { 13747ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes Log.i(TAG, "Could not call getMaxAvailableHeightMethod(View, int, boolean)" 13757ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes + " on PopupWindow. Using the public version."); 13767ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } 13777ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } 13787ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes return mPopup.getMaxAvailableHeight(anchor, yOffset); 13797ede35a254a543305421b3b2d88f11ad2d0466e6Chris Banes } 13803565bf7048dfa3c5b5593d0df2259bd856f3b987Anirudh Dewani}