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