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