19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viveretteimport com.android.internal.R; 20f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasbergimport com.android.internal.view.menu.ShowableListMenu; 21b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 227b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbyeimport android.annotation.DrawableRes; 23b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viveretteimport android.annotation.Nullable; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.Widget; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnClickListener; 29b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viveretteimport android.content.res.Resources; 302add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viveretteimport android.content.res.Resources.Theme; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DataSetObserver; 335f83a6017bacb513610df83a36b1f55953e65ad4Adam Powellimport android.graphics.Rect; 348db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powellimport android.graphics.drawable.Drawable; 35d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viveretteimport android.os.Build; 36235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powellimport android.os.Parcel; 37235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powellimport android.os.Parcelable; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 39d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powellimport android.util.Log; 40b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viveretteimport android.view.ContextThemeWrapper; 41a39b987bb761899636ae1e3669d1343499d04ebdAdam Powellimport android.view.Gravity; 42ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viveretteimport android.view.MotionEvent; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 45f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.view.ViewTreeObserver; 46f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.view.ViewTreeObserver.OnGlobalLayoutListener; 478a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 48f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.widget.PopupWindow.OnDismissListener; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that displays one child at a time and lets the user pick among them. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The items in the Spinner come from the {@link Adapter} associated with 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this view. 5441ec65355bd6ded652769725b276d47c54a0d913Scott Main * 554c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/controls/spinner.html">Spinners</a> guide.</p> 5695148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park * 574c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownSelector 584c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownWidth 594c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_gravity 604c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_popupBackground 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Spinner_prompt 624c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_spinnerMode 6340ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset 6440ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project@Widget 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Spinner extends AbsSpinner implements OnClickListener { 68c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private static final String TAG = "Spinner"; 6995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park 7050f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell // Only measure this many items to get a decent max width. 7150f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell private static final int MAX_ITEMS_MEASURED = 15; 7250f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell 73c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 74c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Use a dialog window for selecting spinner options. 75c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 76c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public static final int MODE_DIALOG = 0; 7795148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park 78c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 79c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Use a dropdown anchored to the Spinner for selecting spinner options. 80c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 81c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public static final int MODE_DROPDOWN = 1; 82b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 83fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 84fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * Use the theme-supplied value to select the dropdown mode. 85fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 86fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell private static final int MODE_THEME = -1; 87ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette 88cd703b62359f887b86920cf652c2d77246e39391Alan Viverette private final Rect mTempRect = new Rect(); 89cd703b62359f887b86920cf652c2d77246e39391Alan Viverette 90b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette /** Context used to inflate the popup window or dialog. */ 91cd703b62359f887b86920cf652c2d77246e39391Alan Viverette private final Context mPopupContext; 92b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 93ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette /** Forwarding listener used to implement drag-to-open. */ 94ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette private ForwardingListener mForwardingListener; 95ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette 963f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette /** Temporary holder for setAdapter() calls from the super constructor. */ 973f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette private SpinnerAdapter mTempAdapter; 983f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette 99c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private SpinnerPopup mPopup; 1008db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell int mDropDownWidth; 101fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell 102a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell private int mGravity; 10342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell private boolean mDisableChildrenWhenDisabled; 104a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell 105fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 106cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme. 107fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 108fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param context The Context the view is running in, through which it can 109cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 110fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Spinner(Context context) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 115fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 116cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme and the supplied 117fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * mode of displaying choices. <code>mode</code> may be one of 118fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * {@link #MODE_DIALOG} or {@link #MODE_DROPDOWN}. 119fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 120fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param context The Context the view is running in, through which it can 121cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 122cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * @param mode Constant describing how the user will select choices from 123cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * the spinner. 124fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 125fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @see #MODE_DIALOG 126fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @see #MODE_DROPDOWN 127fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 128fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell public Spinner(Context context, int mode) { 129fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell this(context, null, com.android.internal.R.attr.spinnerStyle, mode); 130fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell } 131fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell 132fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 133cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme and the supplied 134cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * attribute set. 135fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 136fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param context The Context the view is running in, through which it can 137cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 138fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param attrs The attributes of the XML tag that is inflating the view. 139fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Spinner(Context context, AttributeSet attrs) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, com.android.internal.R.attr.spinnerStyle); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 144fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 145cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme, the supplied 146cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * attribute set, and default style attribute. 147fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 148fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param context The Context the view is running in, through which it can 149cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 150fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param attrs The attributes of the XML tag that is inflating the view. 151617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 152cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * reference to a style resource that supplies default 153cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * values for the view. Can be 0 to not look for 154cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * defaults. 155fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 156617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public Spinner(Context context, AttributeSet attrs, int defStyleAttr) { 157617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0, MODE_THEME); 158fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell } 159fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell 160fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell /** 161cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme, the supplied 162cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * attribute set, and default style attribute. <code>mode</code> may be one 163cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * of {@link #MODE_DIALOG} or {@link #MODE_DROPDOWN} and determines how the 164cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * user will select choices from the spinner. 165fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * 166fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param context The Context the view is running in, through which it can 167cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 168fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @param attrs The attributes of the XML tag that is inflating the view. 169617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 170cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * reference to a style resource that supplies default 171cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * values for the view. Can be 0 to not look for defaults. 172cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * @param mode Constant describing how the user will select choices from the 173cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * spinner. 174617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * 175617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @see #MODE_DIALOG 176617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @see #MODE_DROPDOWN 177617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette */ 178617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public Spinner(Context context, AttributeSet attrs, int defStyleAttr, int mode) { 179617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0, mode); 180617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 181617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 182617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette /** 183cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context's theme, the supplied 184cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * attribute set, and default styles. <code>mode</code> may be one of 185cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * {@link #MODE_DIALOG} or {@link #MODE_DROPDOWN} and determines how the 186cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * user will select choices from the spinner. 187617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * 188617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param context The Context the view is running in, through which it can 189cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * access the current theme, resources, etc. 190617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param attrs The attributes of the XML tag that is inflating the view. 191617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 192cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * reference to a style resource that supplies default 193cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * values for the view. Can be 0 to not look for 194cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * defaults. 195617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * @param defStyleRes A resource identifier of a style resource that 196cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * supplies default values for the view, used only if 197cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * defStyleAttr is 0 or can not be found in the theme. 198cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Can be 0 to not look for defaults. 199cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * @param mode Constant describing how the user will select choices from 200cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * the spinner. 201617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette * 202fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @see #MODE_DIALOG 203fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell * @see #MODE_DROPDOWN 204fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell */ 2053f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette public Spinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, 2063f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette int mode) { 2073f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette this(context, attrs, defStyleAttr, defStyleRes, mode, null); 2083f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 2093f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette 2103f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette /** 211cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * Constructs a new spinner with the given context, the supplied attribute 212cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * set, default styles, popup mode (one of {@link #MODE_DIALOG} or 213cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * {@link #MODE_DROPDOWN}), and the theme against which the popup should be 214cd703b62359f887b86920cf652c2d77246e39391Alan Viverette * inflated. 2153f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * 2163f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @param context The context against which the view is inflated, which 2173f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * provides access to the current theme, resources, etc. 2183f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @param attrs The attributes of the XML tag that is inflating the view. 2193f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @param defStyleAttr An attribute in the current theme that contains a 2203f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * reference to a style resource that supplies default 2213f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * values for the view. Can be 0 to not look for 2223f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * defaults. 2233f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @param defStyleRes A resource identifier of a style resource that 2243f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * supplies default values for the view, used only if 2253f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * defStyleAttr is 0 or can not be found in the theme. 2263f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * Can be 0 to not look for defaults. 2273f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @param mode Constant describing how the user will select choices from 2283f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * the spinner. 2292add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette * @param popupTheme The theme against which the dialog or dropdown popup 2302add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette * should be inflated. May be {@code null} to use the 2312add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette * view theme. If set, this will override any value 2322add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette * specified by 2332add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette * {@link android.R.styleable#Spinner_popupTheme}. 2343f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * 2353f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @see #MODE_DIALOG 2363f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette * @see #MODE_DROPDOWN 2373f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette */ 2383f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette public Spinner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes, int mode, 2392add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette Theme popupTheme) { 240617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 242617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 2433f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette attrs, R.styleable.Spinner, defStyleAttr, defStyleRes); 244fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell 2452add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette if (popupTheme != null) { 2462add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette mPopupContext = new ContextThemeWrapper(context, popupTheme); 247b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette } else { 2483f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette final int popupThemeResId = a.getResourceId(R.styleable.Spinner_popupTheme, 0); 2493f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette if (popupThemeResId != 0) { 2503f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopupContext = new ContextThemeWrapper(context, popupThemeResId); 2513f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } else { 2523f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopupContext = context; 2533f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 254b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette } 255b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 256fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell if (mode == MODE_THEME) { 2573f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mode = a.getInt(R.styleable.Spinner_spinnerMode, MODE_DIALOG); 258fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell } 259b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 260c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell switch (mode) { 2613f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette case MODE_DIALOG: { 2623f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopup = new DialogPopup(); 2633f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopup.setPromptText(a.getString(R.styleable.Spinner_prompt)); 2643f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette break; 2653f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 2663f10b1c8f841113b93d2dfecdd84a1dfb1008fafDaisuke Miyakawa 2673f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette case MODE_DROPDOWN: { 2683f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette final DropdownPopup popup = new DropdownPopup( 2693f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopupContext, attrs, defStyleAttr, defStyleRes); 2703f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette final TypedArray pa = mPopupContext.obtainStyledAttributes( 2713f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette attrs, R.styleable.Spinner, defStyleAttr, defStyleRes); 2723f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mDropDownWidth = pa.getLayoutDimension(R.styleable.Spinner_dropDownWidth, 2733f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette ViewGroup.LayoutParams.WRAP_CONTENT); 274850cd726c8573665316a732423cb0521e69bbeeeAlan Viverette if (pa.hasValueOrEmpty(R.styleable.Spinner_dropDownSelector)) { 275850cd726c8573665316a732423cb0521e69bbeeeAlan Viverette popup.setListSelector(pa.getDrawable( 276850cd726c8573665316a732423cb0521e69bbeeeAlan Viverette R.styleable.Spinner_dropDownSelector)); 277850cd726c8573665316a732423cb0521e69bbeeeAlan Viverette } 2783f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette popup.setBackgroundDrawable(pa.getDrawable(R.styleable.Spinner_popupBackground)); 2793f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette popup.setPromptText(a.getString(R.styleable.Spinner_prompt)); 2803f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette pa.recycle(); 2813f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette 2823f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopup = popup; 2833f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mForwardingListener = new ForwardingListener(this) { 2843f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette @Override 285f44d90b5c247f0629201d1fa322b83fa55b20608Oren Blasberg public ShowableListMenu getPopup() { 2863f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette return popup; 2873f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 288ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette 2893f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette @Override 2903f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette public boolean onForwardingStarted() { 2913f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette if (!mPopup.isShowing()) { 2923f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopup.show(getTextDirection(), getTextAlignment()); 2933f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 2943f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette return true; 295ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette } 2963f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette }; 2973f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette break; 2983f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 299c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 300f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio 3013f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mGravity = a.getInt(R.styleable.Spinner_gravity, Gravity.CENTER); 30242b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell mDisableChildrenWhenDisabled = a.getBoolean( 3033f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette R.styleable.Spinner_disableChildrenWhenDisabled, false); 30442b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 30668464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell 30768464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell // Base constructor can call setAdapter before we initialize mPopup. 30868464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell // Finish setting things up if this happened. 30968464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell if (mTempAdapter != null) { 3103f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette setAdapter(mTempAdapter); 31168464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell mTempAdapter = null; 31268464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 314a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell 315d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 316b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * @return the context used to inflate the Spinner's popup or dialog window 317b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette */ 318b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette public Context getPopupContext() { 319b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette return mPopupContext; 320b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette } 321b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 322b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette /** 323d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set the background drawable for the spinner's popup window of choices. 324d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes. 325d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 326d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @param background Background drawable 327d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 328d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Spinner_popupBackground 329d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 330d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setPopupBackgroundDrawable(Drawable background) { 331d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell if (!(mPopup instanceof DropdownPopup)) { 332d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell Log.e(TAG, "setPopupBackgroundDrawable: incompatible spinner mode; ignoring..."); 333d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return; 334d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 335b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette mPopup.setBackgroundDrawable(background); 336d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 337d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 338d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 339d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set the background drawable for the spinner's popup window of choices. 340d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes. 341d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 342dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell * @param resId Resource ID of a background drawable 343d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 344d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Spinner_popupBackground 345d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 3467b9c912f536925ac6ec43935d6e97506851b33d6Tor Norbye public void setPopupBackgroundResource(@DrawableRes int resId) { 347b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette setPopupBackgroundDrawable(getPopupContext().getDrawable(resId)); 348d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 349d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 350d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 351d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Get the background drawable for the spinner's popup window of choices. 352d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; other modes will return null. 353d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 354d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @return background Background drawable 355d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 356d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Spinner_popupBackground 357d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 358d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public Drawable getPopupBackground() { 359d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return mPopup.getBackground(); 360d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 361d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 362d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 363d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set a vertical offset in pixels for the spinner's popup window of choices. 364d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes. 365d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 366d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @param pixels Vertical offset in pixels 367d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 36840ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset 369d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 370d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setDropDownVerticalOffset(int pixels) { 371d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell mPopup.setVerticalOffset(pixels); 372d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 373d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 374d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 375d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Get the configured vertical offset in pixels for the spinner's popup window of choices. 376d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0. 377d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 378d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @return Vertical offset in pixels 379d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 38040ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownVerticalOffset 381d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 382d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getDropDownVerticalOffset() { 383d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return mPopup.getVerticalOffset(); 384d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 385d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 386d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 387d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set a horizontal offset in pixels for the spinner's popup window of choices. 388d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes. 389d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 390d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @param pixels Horizontal offset in pixels 391d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 39240ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset 393d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 394d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setDropDownHorizontalOffset(int pixels) { 395d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell mPopup.setHorizontalOffset(pixels); 396d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 397d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 398d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 399d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Get the configured horizontal offset in pixels for the spinner's popup window of choices. 400d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0. 401d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 402d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @return Horizontal offset in pixels 403d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 40440ce0707143895d8ea07e8a57e1dff38c0ac303bAlan Viverette * @attr ref android.R.styleable#ListPopupWindow_dropDownHorizontalOffset 405d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 406d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getDropDownHorizontalOffset() { 407d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return mPopup.getHorizontalOffset(); 408d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 409d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 410d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 411d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Set the width of the spinner's popup window of choices in pixels. This value 412d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * may also be set to {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} 413d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * to match the width of the Spinner itself, or 414d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size 415d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * of contained dropdown list items. 416d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 417d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * <p>Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.</p> 418d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 419d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @param pixels Width in pixels, WRAP_CONTENT, or MATCH_PARENT 420d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 421d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Spinner_dropDownWidth 422d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 423d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setDropDownWidth(int pixels) { 424d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell if (!(mPopup instanceof DropdownPopup)) { 425d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell Log.e(TAG, "Cannot set dropdown width for MODE_DIALOG, ignoring"); 426d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return; 427d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 428d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell mDropDownWidth = pixels; 429d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 430d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 431d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 432d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Get the configured width of the spinner's popup window of choices in pixels. 433d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * The returned value may also be {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT} 434d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * meaning the popup window will match the width of the Spinner itself, or 435d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size 436d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * of contained dropdown list items. 437d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 438d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @return Width in pixels, WRAP_CONTENT, or MATCH_PARENT 439d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 440d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @attr ref android.R.styleable#Spinner_dropDownWidth 441d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 442d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getDropDownWidth() { 443d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return mDropDownWidth; 444d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 445d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 44642b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell @Override 44742b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell public void setEnabled(boolean enabled) { 44842b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell super.setEnabled(enabled); 44942b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell if (mDisableChildrenWhenDisabled) { 45042b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell final int count = getChildCount(); 45142b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell for (int i = 0; i < count; i++) { 45242b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell getChildAt(i).setEnabled(enabled); 45342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell } 45442b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell } 45542b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell } 45642b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell 457a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell /** 458a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * Describes how the selected item view is positioned. Currently only the horizontal component 459a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * is used. The default is determined by the current theme. 460a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * 461a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * @param gravity See {@link android.view.Gravity} 462a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * 463a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell * @attr ref android.R.styleable#Spinner_gravity 464a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell */ 465a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell public void setGravity(int gravity) { 466a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell if (mGravity != gravity) { 467a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) { 46838d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio gravity |= Gravity.START; 469a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 470a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell mGravity = gravity; 471a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell requestLayout(); 472a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 473a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 474a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell 475d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell /** 476d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * Describes how the selected item view is positioned. The default is determined by the 477d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * current theme. 478d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * 479d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell * @return A {@link android.view.Gravity Gravity} value 480d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell */ 481d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getGravity() { 482d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return mGravity; 483d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 484d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 485a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette /** 486b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * Sets the {@link SpinnerAdapter} used to provide the data which backs 487b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * this Spinner. 488b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * <p> 489b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * If this Spinner has a popup theme set in XML via the 490b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * {@link android.R.styleable#Spinner_popupTheme popupTheme} attribute, the 491b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * adapter should inflate drop-down views using the same theme. The easiest 492b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * way to achieve this is by using {@link #getPopupContext()} to obtain a 493b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * layout inflater for use in 494b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * {@link SpinnerAdapter#getDropDownView(int, View, ViewGroup)}. 495a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * <p> 496b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * Spinner overrides {@link Adapter#getViewTypeCount()} on the 497a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * Adapter associated with this view. Calling 498a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * {@link Adapter#getItemViewType(int) getItemViewType(int)} on the object 499a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * returned from {@link #getAdapter()} will always return 0. Calling 500a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * {@link Adapter#getViewTypeCount() getViewTypeCount()} will always return 501955d8d69ea6caabce1461dc25b339b9bf9dc61a6Dianne Hackborn * 1. On API {@link Build.VERSION_CODES#LOLLIPOP} and above, attempting to set an 502d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * adapter with more than one view type will throw an 503d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * {@link IllegalArgumentException}. 504d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * 505d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * @param adapter the adapter to set 506a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * 507a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette * @see AbsSpinner#setAdapter(SpinnerAdapter) 508d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * @throws IllegalArgumentException if the adapter has more than one view 509d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette * type 510a089ddecaf2ca5cb56ba62af5ece279fb9cb6c0fAlan Viverette */ 511c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell @Override 512c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setAdapter(SpinnerAdapter adapter) { 5133f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette // The super constructor may call setAdapter before we're prepared. 5143f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette // Postpone doing anything until we've finished construction. 5153f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette if (mPopup == null) { 5163f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mTempAdapter = adapter; 5173f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette return; 5183f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette } 5193f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette 520c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell super.setAdapter(adapter); 52168464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell 5226a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell mRecycler.clear(); 5236a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell 524d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; 525955d8d69ea6caabce1461dc25b339b9bf9dc61a6Dianne Hackborn if (targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP 526d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette && adapter != null && adapter.getViewTypeCount() != 1) { 527d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette throw new IllegalArgumentException("Spinner adapter view type count must be 1"); 528d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette } 529d52697784fcf91b62a1a487a0229c1a6548853cdAlan Viverette 5303f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette final Context popupContext = mPopupContext == null ? mContext : mPopupContext; 5313f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette mPopup.setAdapter(new DropDownAdapter(adapter, popupContext.getTheme())); 532c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getBaseline() { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = null; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getChildCount() > 0) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(0); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mAdapter != null && mAdapter.getCount() > 0) { 5416a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell child = makeView(0, false); 54222e92e55576e2c723c320824de08d78326379aebAdam Powell mRecycler.put(0, child); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child != null) { 546160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell final int childBaseline = child.getBaseline(); 547160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell return childBaseline >= 0 ? child.getTop() + childBaseline : -1; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5535275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy @Override 5545275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy protected void onDetachedFromWindow() { 5555275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy super.onDetachedFromWindow(); 5565275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy 5575275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy if (mPopup != null && mPopup.isShowing()) { 5585275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy mPopup.dismiss(); 5595275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy } 5605275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy } 5615275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>A spinner does not support item click events. Calling this method 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will raise an exception.</p> 5654c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>Instead use {@link AdapterView#setOnItemSelectedListener}. 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param l this listener will be ignored 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnItemClickListener(OnItemClickListener l) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException("setOnItemClickListener cannot be used with a spinner."); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 574c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell /** 575c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell * @hide internal use only 576c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell */ 577c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell public void setOnItemClickListenerInt(OnItemClickListener l) { 578c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell super.setOnItemClickListener(l); 579c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell } 580c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell 581a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell @Override 582ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette public boolean onTouchEvent(MotionEvent event) { 583ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette if (mForwardingListener != null && mForwardingListener.onTouch(this, event)) { 584ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette return true; 585ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette } 586ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette 587ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette return super.onTouchEvent(event); 588ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette } 589ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette 590ca6a3611cdb28a514834adba35fcce2da6f2e7c2Alan Viverette @Override 591a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 592a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell super.onMeasure(widthMeasureSpec, heightMeasureSpec); 593a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { 594a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell final int measuredWidth = getMeasuredWidth(); 59519fd164408033eb46a40abd514aa0bf698525e55Adam Powell setMeasuredDimension(Math.min(Math.max(measuredWidth, 596b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell measureContentWidth(getAdapter(), getBackground())), 597b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell MeasureSpec.getSize(widthMeasureSpec)), 598a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell getMeasuredHeight()); 599a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 600a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 601a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.View#onLayout(boolean,int,int,int,int) 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates and positions all views 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onLayout(boolean changed, int l, int t, int r, int b) { 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onLayout(changed, l, t, r, b); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLayout = true; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout(0, false); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLayout = false; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates and positions all views for this Spinner. 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 61938d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio * @param delta Change in the selected position. +1 means selection is moving to the right, 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * so views are scrolling to the left. -1 means selection is moving to the left. 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void layout(int delta, boolean animate) { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childrenLeft = mSpinnerPadding.left; 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataChanged) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleDataChanged(); 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handle the empty set by removing all views 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount == 0) { 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNextSelectedPosition >= 0) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(mNextSelectedPosition); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycleAllViews(); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clear out old views 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeAllViewsInLayout(); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 646a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell // Make selected view and position it 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = mSelectedPosition; 64872d574cbe0448f125e452140f13dce20e02ed960Adam Powell 64972d574cbe0448f125e452140f13dce20e02ed960Adam Powell if (mAdapter != null) { 6506a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell View sel = makeView(mSelectedPosition, true); 65172d574cbe0448f125e452140f13dce20e02ed960Adam Powell int width = sel.getMeasuredWidth(); 65272d574cbe0448f125e452140f13dce20e02ed960Adam Powell int selectedOffset = childrenLeft; 65372d574cbe0448f125e452140f13dce20e02ed960Adam Powell final int layoutDirection = getLayoutDirection(); 65472d574cbe0448f125e452140f13dce20e02ed960Adam Powell final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection); 65572d574cbe0448f125e452140f13dce20e02ed960Adam Powell switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { 65672d574cbe0448f125e452140f13dce20e02ed960Adam Powell case Gravity.CENTER_HORIZONTAL: 65772d574cbe0448f125e452140f13dce20e02ed960Adam Powell selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2); 65872d574cbe0448f125e452140f13dce20e02ed960Adam Powell break; 65972d574cbe0448f125e452140f13dce20e02ed960Adam Powell case Gravity.RIGHT: 66072d574cbe0448f125e452140f13dce20e02ed960Adam Powell selectedOffset = childrenLeft + childrenWidth - width; 66172d574cbe0448f125e452140f13dce20e02ed960Adam Powell break; 66272d574cbe0448f125e452140f13dce20e02ed960Adam Powell } 66372d574cbe0448f125e452140f13dce20e02ed960Adam Powell sel.offsetLeftAndRight(selectedOffset); 664a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell } 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Flush any cached views that did not get reused above 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRecycler.clear(); 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataChanged = false; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedSync = false; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(mSelectedPosition); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Obtain a view, either by pulling an existing view from the recycler or 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by getting a new one from the adapter. If we are animating, make sure 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is enough information in the view's layout parameters to animate 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the old to new positions. 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position Position in the spinner for the view to obtain 6856a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell * @param addChild true to add the child to the spinner, false to obtain and configure only. 6866a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell * @return A view for the given position 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6886a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell private View makeView(int position, boolean addChild) { 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mDataChanged) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = mRecycler.get(position); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child != null) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Position the view 6956a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell setUpChild(child, addChild); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Nothing found in the recycler -- ask the adapter for a view 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = mAdapter.getView(position, null, this); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Position the view 7056a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell setUpChild(child, addChild); 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper for makeAndAddView to set the position of a view 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and fill out its layout paramters. 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The view to position 7156a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell * @param addChild true if the child should be added to the Spinner during setup 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7176a221b3f85fbe7cbfbd11b9eeb672baca27faec2Adam Powell private void setUpChild(View child, boolean addChild) { 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Respect layout params that are already in the view. Otherwise 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make some up... 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup.LayoutParams lp = child.getLayoutParams(); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lp == null) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp = generateDefaultLayoutParams(); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 72625c6cd61d42c4d1f833f76ab5842d76ef0820963Alan Viverette addViewInLayout(child, 0, lp); 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.setSelected(hasFocus()); 72942b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell if (mDisableChildrenWhenDisabled) { 73042b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell child.setEnabled(isEnabled()); 73142b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell } 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get measure specs 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec, 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height); 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpinnerPadding.left + mSpinnerPadding.right, lp.width); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Measure child 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childLeft; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childRight; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Position vertically based on gravity setting 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childTop = mSpinnerPadding.top 747189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn + ((getMeasuredHeight() - mSpinnerPadding.bottom - 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpinnerPadding.top - child.getMeasuredHeight()) / 2); 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childBottom = childTop + child.getMeasuredHeight(); 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width = child.getMeasuredWidth(); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childLeft = 0; 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childRight = childLeft + width; 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.layout(childLeft, childTop, childRight, childBottom); 75625c6cd61d42c4d1f833f76ab5842d76ef0820963Alan Viverette 75725c6cd61d42c4d1f833f76ab5842d76ef0820963Alan Viverette if (!addChild) { 75825c6cd61d42c4d1f833f76ab5842d76ef0820963Alan Viverette removeViewInLayout(child); 75925c6cd61d42c4d1f833f76ab5842d76ef0820963Alan Viverette } 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performClick() { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = super.performClick(); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!handled) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = true; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell if (!mPopup.isShowing()) { 770f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio mPopup.show(getTextDirection(), getTextAlignment()); 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7768a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(DialogInterface dialog, int which) { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(which); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dialog.dismiss(); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7828a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 783a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 784a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return Spinner.class.getName(); 7858a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 7868a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 787a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 7888a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 789a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 790a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 791058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette 792058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette if (mAdapter != null) { 793cb8ed39b3fb591be60b9fb1799d4ea4530eab758Svetoslav Ganov info.setCanOpenPopup(true); 794058ac7cfe5bb7b9ecc411b94622ac3f31a7fa25eAlan Viverette } 7958a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 7968a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the prompt to display when the dialog is shown. 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param prompt the prompt to set 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setPrompt(CharSequence prompt) { 802c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell mPopup.setPromptText(prompt); 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the prompt to display when the dialog is shown. 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param promptId the resource ID of the prompt to display when the dialog is shown 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setPromptId(int promptId) { 810c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setPrompt(getContext().getText(promptId)); 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The prompt to display when the dialog is shown 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence getPrompt() { 817c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell return mPopup.getHintText(); 818c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 81919fd164408033eb46a40abd514aa0bf698525e55Adam Powell 820b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell int measureContentWidth(SpinnerAdapter adapter, Drawable background) { 82119fd164408033eb46a40abd514aa0bf698525e55Adam Powell if (adapter == null) { 82219fd164408033eb46a40abd514aa0bf698525e55Adam Powell return 0; 82319fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 82419fd164408033eb46a40abd514aa0bf698525e55Adam Powell 82519fd164408033eb46a40abd514aa0bf698525e55Adam Powell int width = 0; 82619fd164408033eb46a40abd514aa0bf698525e55Adam Powell View itemView = null; 82719fd164408033eb46a40abd514aa0bf698525e55Adam Powell int itemType = 0; 82819fd164408033eb46a40abd514aa0bf698525e55Adam Powell final int widthMeasureSpec = 829d5dbf4b2a09c9cf2d17fa6af3fdf75d1fb774056Adam Powell MeasureSpec.makeSafeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED); 83019fd164408033eb46a40abd514aa0bf698525e55Adam Powell final int heightMeasureSpec = 831d5dbf4b2a09c9cf2d17fa6af3fdf75d1fb774056Adam Powell MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED); 83219fd164408033eb46a40abd514aa0bf698525e55Adam Powell 83319fd164408033eb46a40abd514aa0bf698525e55Adam Powell // Make sure the number of items we'll measure is capped. If it's a huge data set 83419fd164408033eb46a40abd514aa0bf698525e55Adam Powell // with wildly varying sizes, oh well. 835b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell int start = Math.max(0, getSelectedItemPosition()); 836b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell final int end = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED); 837b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell final int count = end - start; 838b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell start = Math.max(0, start - (MAX_ITEMS_MEASURED - count)); 839b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell for (int i = start; i < end; i++) { 84019fd164408033eb46a40abd514aa0bf698525e55Adam Powell final int positionType = adapter.getItemViewType(i); 84119fd164408033eb46a40abd514aa0bf698525e55Adam Powell if (positionType != itemType) { 84219fd164408033eb46a40abd514aa0bf698525e55Adam Powell itemType = positionType; 84319fd164408033eb46a40abd514aa0bf698525e55Adam Powell itemView = null; 84419fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 84519fd164408033eb46a40abd514aa0bf698525e55Adam Powell itemView = adapter.getView(i, itemView, this); 84619fd164408033eb46a40abd514aa0bf698525e55Adam Powell if (itemView.getLayoutParams() == null) { 84719fd164408033eb46a40abd514aa0bf698525e55Adam Powell itemView.setLayoutParams(new ViewGroup.LayoutParams( 84819fd164408033eb46a40abd514aa0bf698525e55Adam Powell ViewGroup.LayoutParams.WRAP_CONTENT, 84919fd164408033eb46a40abd514aa0bf698525e55Adam Powell ViewGroup.LayoutParams.WRAP_CONTENT)); 85019fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 85119fd164408033eb46a40abd514aa0bf698525e55Adam Powell itemView.measure(widthMeasureSpec, heightMeasureSpec); 85219fd164408033eb46a40abd514aa0bf698525e55Adam Powell width = Math.max(width, itemView.getMeasuredWidth()); 85319fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 85419fd164408033eb46a40abd514aa0bf698525e55Adam Powell 85519fd164408033eb46a40abd514aa0bf698525e55Adam Powell // Add background padding to measured width 856b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell if (background != null) { 857b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell background.getPadding(mTempRect); 85819fd164408033eb46a40abd514aa0bf698525e55Adam Powell width += mTempRect.left + mTempRect.right; 85919fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 86019fd164408033eb46a40abd514aa0bf698525e55Adam Powell 86119fd164408033eb46a40abd514aa0bf698525e55Adam Powell return width; 86219fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 86319fd164408033eb46a40abd514aa0bf698525e55Adam Powell 864235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell @Override 865235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public Parcelable onSaveInstanceState() { 866235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell final SavedState ss = new SavedState(super.onSaveInstanceState()); 867235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell ss.showDropdown = mPopup != null && mPopup.isShowing(); 868235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell return ss; 869235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 870235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 871235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell @Override 872235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public void onRestoreInstanceState(Parcelable state) { 873235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell SavedState ss = (SavedState) state; 874235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 875235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell super.onRestoreInstanceState(ss.getSuperState()); 876235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 877235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell if (ss.showDropdown) { 878235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell ViewTreeObserver vto = getViewTreeObserver(); 879235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell if (vto != null) { 880235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() { 881235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell @Override 882235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public void onGlobalLayout() { 883235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell if (!mPopup.isShowing()) { 884f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio mPopup.show(getTextDirection(), getTextAlignment()); 885235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 886235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell final ViewTreeObserver vto = getViewTreeObserver(); 887235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell if (vto != null) { 888235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell vto.removeOnGlobalLayoutListener(this); 889235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 890235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 891235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell }; 892235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell vto.addOnGlobalLayoutListener(listener); 893235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 894235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 895235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 896235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 897235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell static class SavedState extends AbsSpinner.SavedState { 898235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell boolean showDropdown; 899235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 900235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell SavedState(Parcelable superState) { 901235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell super(superState); 902235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 903235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 904235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell private SavedState(Parcel in) { 905235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell super(in); 906235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell showDropdown = in.readByte() != 0; 907235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 908235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 909235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell @Override 910235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public void writeToParcel(Parcel out, int flags) { 911235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell super.writeToParcel(out, flags); 912235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell out.writeByte((byte) (showDropdown ? 1 : 0)); 913235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 914235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 915235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public static final Parcelable.Creator<SavedState> CREATOR = 916235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell new Parcelable.Creator<SavedState>() { 917235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public SavedState createFromParcel(Parcel in) { 918235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell return new SavedState(in); 919235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 920235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 921235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell public SavedState[] newArray(int size) { 922235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell return new SavedState[size]; 923235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 924235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell }; 925235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 926235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into a ListAdapter.</p> 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class DropDownAdapter implements ListAdapter, SpinnerAdapter { 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SpinnerAdapter mAdapter; 9331f09c8314701c1d09be8e350344c58241905677bAdam Powell private ListAdapter mListAdapter; 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 936b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * Creates a new ListAdapter wrapper for the specified adapter. 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 938b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * @param adapter the SpinnerAdapter to transform into a ListAdapter 939b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * @param dropDownTheme the theme against which to inflate drop-down 940b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette * views, may be {@null} to use default theme 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 942b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette public DropDownAdapter(@Nullable SpinnerAdapter adapter, 943b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette @Nullable Resources.Theme dropDownTheme) { 944b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette mAdapter = adapter; 945b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 9461f09c8314701c1d09be8e350344c58241905677bAdam Powell if (adapter instanceof ListAdapter) { 947b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette mListAdapter = (ListAdapter) adapter; 948b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette } 949b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 9502add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette if (dropDownTheme != null && adapter instanceof ThemedSpinnerAdapter) { 9512add9bcf8c33c59f300551bdb0671bbff0b55794Alan Viverette final ThemedSpinnerAdapter themedAdapter = (ThemedSpinnerAdapter) adapter; 952b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette if (themedAdapter.getDropDownViewTheme() == null) { 953b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette themedAdapter.setDropDownViewTheme(dropDownTheme); 954b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette } 9551f09c8314701c1d09be8e350344c58241905677bAdam Powell } 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getCount() { 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter == null ? 0 : mAdapter.getCount(); 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object getItem(int position) { 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter == null ? null : mAdapter.getItem(position); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getItemId(int position) { 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter == null ? -1 : mAdapter.getItemId(position); 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getView(int position, View convertView, ViewGroup parent) { 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getDropDownView(position, convertView, parent); 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View getDropDownView(int position, View convertView, ViewGroup parent) { 975f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio return (mAdapter == null) ? null : mAdapter.getDropDownView(position, convertView, parent); 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean hasStableIds() { 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter != null && mAdapter.hasStableIds(); 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void registerDataSetObserver(DataSetObserver observer) { 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter != null) { 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.registerDataSetObserver(observer); 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void unregisterDataSetObserver(DataSetObserver observer) { 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter != null) { 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.unregisterDataSetObserver(observer); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9951f09c8314701c1d09be8e350344c58241905677bAdam Powell * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. 9961f09c8314701c1d09be8e350344c58241905677bAdam Powell * Otherwise, return true. 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean areAllItemsEnabled() { 9991f09c8314701c1d09be8e350344c58241905677bAdam Powell final ListAdapter adapter = mListAdapter; 10001f09c8314701c1d09be8e350344c58241905677bAdam Powell if (adapter != null) { 10011f09c8314701c1d09be8e350344c58241905677bAdam Powell return adapter.areAllItemsEnabled(); 10021f09c8314701c1d09be8e350344c58241905677bAdam Powell } else { 10031f09c8314701c1d09be8e350344c58241905677bAdam Powell return true; 10041f09c8314701c1d09be8e350344c58241905677bAdam Powell } 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10081f09c8314701c1d09be8e350344c58241905677bAdam Powell * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call. 10091f09c8314701c1d09be8e350344c58241905677bAdam Powell * Otherwise, return true. 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEnabled(int position) { 10121f09c8314701c1d09be8e350344c58241905677bAdam Powell final ListAdapter adapter = mListAdapter; 10131f09c8314701c1d09be8e350344c58241905677bAdam Powell if (adapter != null) { 10141f09c8314701c1d09be8e350344c58241905677bAdam Powell return adapter.isEnabled(position); 10151f09c8314701c1d09be8e350344c58241905677bAdam Powell } else { 10161f09c8314701c1d09be8e350344c58241905677bAdam Powell return true; 10171f09c8314701c1d09be8e350344c58241905677bAdam Powell } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getItemViewType(int position) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getViewTypeCount() { 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 1; 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isEmpty() { 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getCount() == 0; 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1032c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1033c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 1034c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Implements some sort of popup selection interface for selecting a spinner option. 1035c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Allows for different spinner modes. 1036c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 1037c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private interface SpinnerPopup { 1038c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setAdapter(ListAdapter adapter); 1039c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1040c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 1041c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Show the popup 1042c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 1043f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio public void show(int textDirection, int textAlignment); 1044f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio 1045c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 1046c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Dismiss the popup 1047c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 1048c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void dismiss(); 1049c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1050c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 1051c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @return true if the popup is showing, false otherwise. 1052c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 1053c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public boolean isShowing(); 1054c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1055c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell /** 1056c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * Set hint text to be displayed to the user. This should provide 1057c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * a description of the choice being made. 1058c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell * @param hintText Hint text to set. 1059c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell */ 1060c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setPromptText(CharSequence hintText); 1061c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public CharSequence getHintText(); 1062d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1063d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setBackgroundDrawable(Drawable bg); 1064d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setVerticalOffset(int px); 1065d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setHorizontalOffset(int px); 1066d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public Drawable getBackground(); 1067d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getVerticalOffset(); 1068d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getHorizontalOffset(); 1069c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 10703f221cf32530cdcdb011d1cb543187db501d09dfAlan Viverette 1071c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener { 1072c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private AlertDialog mPopup; 1073c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private ListAdapter mListAdapter; 1074c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private CharSequence mPrompt; 1075c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1076c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void dismiss() { 10772f77f9c03e016f6d453c1fa799c9f68c30acf0ddDaniel if (mPopup != null) { 10782f77f9c03e016f6d453c1fa799c9f68c30acf0ddDaniel mPopup.dismiss(); 10792f77f9c03e016f6d453c1fa799c9f68c30acf0ddDaniel mPopup = null; 10802f77f9c03e016f6d453c1fa799c9f68c30acf0ddDaniel } 1081c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1082c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1083c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public boolean isShowing() { 1084c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell return mPopup != null ? mPopup.isShowing() : false; 1085c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1086c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1087c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setAdapter(ListAdapter adapter) { 1088c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell mListAdapter = adapter; 1089c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1090c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1091c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setPromptText(CharSequence hintText) { 1092c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell mPrompt = hintText; 1093c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1094b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 1095c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public CharSequence getHintText() { 1096c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell return mPrompt; 1097c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1098c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1099f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio public void show(int textDirection, int textAlignment) { 1100b9867eab1de3396fc7e740d6afbc5ee649f416f1Alan Viverette if (mListAdapter == null) { 1101b9867eab1de3396fc7e740d6afbc5ee649f416f1Alan Viverette return; 1102b9867eab1de3396fc7e740d6afbc5ee649f416f1Alan Viverette } 1103b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette AlertDialog.Builder builder = new AlertDialog.Builder(getPopupContext()); 1104c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell if (mPrompt != null) { 1105c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell builder.setTitle(mPrompt); 1106c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1107c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell mPopup = builder.setSingleChoiceItems(mListAdapter, 1108f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio getSelectedItemPosition(), this).create(); 1109f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio final ListView listView = mPopup.getListView(); 1110f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio listView.setTextDirection(textDirection); 1111f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio listView.setTextAlignment(textAlignment); 1112f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio mPopup.show(); 1113c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1114c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1115c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void onClick(DialogInterface dialog, int which) { 1116c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setSelection(which); 1117c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell if (mOnItemClickListener != null) { 1118c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell performItemClick(null, which, mListAdapter.getItemId(which)); 1119c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell } 1120c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell dismiss(); 1121c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1122d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1123d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1124d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setBackgroundDrawable(Drawable bg) { 1125d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell Log.e(TAG, "Cannot set popup background for MODE_DIALOG, ignoring"); 1126d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1127d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1128d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1129d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setVerticalOffset(int px) { 1130d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell Log.e(TAG, "Cannot set vertical offset for MODE_DIALOG, ignoring"); 1131d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1132d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1133d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1134d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public void setHorizontalOffset(int px) { 1135d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell Log.e(TAG, "Cannot set horizontal offset for MODE_DIALOG, ignoring"); 1136d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1137d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1138d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1139d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public Drawable getBackground() { 1140d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return null; 1141d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1142d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1143d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1144d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getVerticalOffset() { 1145d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return 0; 1146d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1147d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell 1148d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell @Override 1149d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell public int getHorizontalOffset() { 1150d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell return 0; 1151d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell } 1152c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1153c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1154c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private class DropdownPopup extends ListPopupWindow implements SpinnerPopup { 1155c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell private CharSequence mHintText; 115619fd164408033eb46a40abd514aa0bf698525e55Adam Powell private ListAdapter mAdapter; 1157efd0811a31e79aa1d3ee6fcaf8d79304872fcc5eChris Yerga 1158617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public DropdownPopup( 1159617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 1160617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 116150f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell 1162c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setAnchorView(Spinner.this); 1163c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setModal(true); 1164be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell setPromptPosition(POSITION_PROMPT_ABOVE); 1165c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setOnItemClickListener(new OnItemClickListener() { 1166c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void onItemClick(AdapterView parent, View v, int position, long id) { 1167c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell Spinner.this.setSelection(position); 1168c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell if (mOnItemClickListener != null) { 1169af3631314f3d9423a3bd77f9cbaea16207b2aff8Adam Powell Spinner.this.performItemClick(v, position, mAdapter.getItemId(position)); 1170c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell } 1171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell dismiss(); 1172c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell }); 1174c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 117619fd164408033eb46a40abd514aa0bf698525e55Adam Powell @Override 117719fd164408033eb46a40abd514aa0bf698525e55Adam Powell public void setAdapter(ListAdapter adapter) { 117819fd164408033eb46a40abd514aa0bf698525e55Adam Powell super.setAdapter(adapter); 117919fd164408033eb46a40abd514aa0bf698525e55Adam Powell mAdapter = adapter; 118019fd164408033eb46a40abd514aa0bf698525e55Adam Powell } 118119fd164408033eb46a40abd514aa0bf698525e55Adam Powell 1182c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public CharSequence getHintText() { 1183c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell return mHintText; 1184c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1185c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell 1186c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell public void setPromptText(CharSequence hintText) { 1187a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell // Hint text is ignored for dropdowns, but maintain it here. 1188c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell mHintText = hintText; 1189c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 11903f10b1c8f841113b93d2dfecdd84a1dfb1008fafDaisuke Miyakawa 1191235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell void computeContentWidth() { 119295148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park final Drawable background = getBackground(); 119338d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio int hOffset = 0; 119495148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park if (background != null) { 119595148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park background.getPadding(mTempRect); 119638d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio hOffset = isLayoutRtl() ? mTempRect.right : -mTempRect.left; 119795148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park } else { 119895148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park mTempRect.left = mTempRect.right = 0; 119995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park } 120095148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park 120162e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell final int spinnerPaddingLeft = Spinner.this.getPaddingLeft(); 120238d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio final int spinnerPaddingRight = Spinner.this.getPaddingRight(); 120338d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio final int spinnerWidth = Spinner.this.getWidth(); 1204235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 12058db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell if (mDropDownWidth == WRAP_CONTENT) { 120695148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park int contentWidth = measureContentWidth( 120795148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park (SpinnerAdapter) mAdapter, getBackground()); 120895148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park final int contentWidthLimit = mContext.getResources() 120995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park .getDisplayMetrics().widthPixels - mTempRect.left - mTempRect.right; 121095148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park if (contentWidth > contentWidthLimit) { 121195148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park contentWidth = contentWidthLimit; 121295148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park } 121362e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell setContentWidth(Math.max( 121495148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park contentWidth, spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight)); 12158db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell } else if (mDropDownWidth == MATCH_PARENT) { 121662e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight); 12178db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell } else { 121862e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell setContentWidth(mDropDownWidth); 12198db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell } 122038d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio 122138d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio if (isLayoutRtl()) { 122238d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio hOffset += spinnerWidth - spinnerPaddingRight - getWidth(); 122338d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio } else { 122438d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio hOffset += spinnerPaddingLeft; 122538d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio } 122638d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio setHorizontalOffset(hOffset); 1227235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 1228235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 1229f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio public void show(int textDirection, int textAlignment) { 1230235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell final boolean wasShowing = isShowing(); 1231235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 1232235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell computeContentWidth(); 1233235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 12346f5e934b96c400f610b1c5ad228cc60cab5d443fAdam Powell setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED); 1235c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell super.show(); 1236f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio final ListView listView = getListView(); 1237f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 1238f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio listView.setTextDirection(textDirection); 1239f80ceed4507292756332d649978ef1b3511430a7Fabrice Di Meglio listView.setTextAlignment(textAlignment); 1240c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell setSelection(Spinner.this.getSelectedItemPosition()); 1241f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell 1242235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell if (wasShowing) { 1243235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell // Skip setting up the layout/dismiss listener below. If we were previously 1244235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell // showing it will still stick around. 1245235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell return; 1246235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } 1247235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 1248f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell // Make sure we hide if our anchor goes away. 1249f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell // TODO: This might be appropriate to push all the way down to PopupWindow, 1250f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell // but it may have other side effects to investigate first. (Text editing handles, etc.) 1251f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1252f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell if (vto != null) { 1253f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell final OnGlobalLayoutListener layoutListener = new OnGlobalLayoutListener() { 1254f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell @Override 1255f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell public void onGlobalLayout() { 1256f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell if (!Spinner.this.isVisibleToUser()) { 1257f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell dismiss(); 1258235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell } else { 1259235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell computeContentWidth(); 1260235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell 1261235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell // Use super.show here to update; we don't want to move the selected 1262235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell // position or adjust other things that would be reset otherwise. 1263235ae5f6fa94634cfc015246817ec49e1f279b62Adam Powell DropdownPopup.super.show(); 1264f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell } 1265f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell } 1266f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell }; 1267f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell vto.addOnGlobalLayoutListener(layoutListener); 1268f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell setOnDismissListener(new OnDismissListener() { 1269f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell @Override public void onDismiss() { 1270f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell final ViewTreeObserver vto = getViewTreeObserver(); 1271f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell if (vto != null) { 1272f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell vto.removeOnGlobalLayoutListener(layoutListener); 1273f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell } 1274f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell } 1275f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell }); 1276f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell } 1277c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1278c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell } 1279b9ead4a91599ca63e947f74f83b67a58bda64a82Alan Viverette 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1281