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
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.Widget;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnClickListener;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DataSetObserver;
265f83a6017bacb513610df83a36b1f55953e65ad4Adam Powellimport android.graphics.Rect;
278db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powellimport android.graphics.drawable.Drawable;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
29d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powellimport android.util.Log;
30a39b987bb761899636ae1e3669d1343499d04ebdAdam Powellimport android.view.Gravity;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
33f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.view.ViewTreeObserver;
34f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.view.ViewTreeObserver.OnGlobalLayoutListener;
358a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
368a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
37f16daf61275de8bb59a0761d5dabc222ce249946Adam Powellimport android.widget.PopupWindow.OnDismissListener;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that displays one child at a time and lets the user pick among them.
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The items in the Spinner come from the {@link Adapter} associated with
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this view.
4441ec65355bd6ded652769725b276d47c54a0d913Scott Main *
454c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/controls/spinner.html">Spinners</a> guide.</p>
4695148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park *
474c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
484c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownSelector
494c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
504c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_dropDownWidth
514c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_gravity
524c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_popupBackground
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#Spinner_prompt
544c359b76f9a030f92a302ba74a528faa170bad4eScott Main * @attr ref android.R.styleable#Spinner_spinnerMode
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project@Widget
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Spinner extends AbsSpinner implements OnClickListener {
58c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private static final String TAG = "Spinner";
5995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park
6050f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell    // Only measure this many items to get a decent max width.
6150f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell    private static final int MAX_ITEMS_MEASURED = 15;
6250f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell
63c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
64c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Use a dialog window for selecting spinner options.
65c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
66c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int MODE_DIALOG = 0;
6795148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park
68c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
69c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Use a dropdown anchored to the Spinner for selecting spinner options.
70c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
71c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public static final int MODE_DROPDOWN = 1;
72c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
73fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
74fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Use the theme-supplied value to select the dropdown mode.
75fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
76fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    private static final int MODE_THEME = -1;
77fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell
78c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private SpinnerPopup mPopup;
7968464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell    private DropDownAdapter mTempAdapter;
808db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell    int mDropDownWidth;
81fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell
82a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    private int mGravity;
8342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell    private boolean mDisableChildrenWhenDisabled;
84a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell
8519fd164408033eb46a40abd514aa0bf698525e55Adam Powell    private Rect mTempRect = new Rect();
8619fd164408033eb46a40abd514aa0bf698525e55Adam Powell
87fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
88fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Construct a new spinner with the given context's theme.
89fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
90fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param context The Context the view is running in, through which it can
91fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        access the current theme, resources, etc.
92fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Spinner(Context context) {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, null);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
97fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
98fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Construct a new spinner with the given context's theme and the supplied
99fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * mode of displaying choices. <code>mode</code> may be one of
100fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * {@link #MODE_DIALOG} or {@link #MODE_DROPDOWN}.
101fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
102fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param context The Context the view is running in, through which it can
103fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        access the current theme, resources, etc.
104fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param mode Constant describing how the user will select choices from the spinner.
105fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
106fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @see #MODE_DIALOG
107fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @see #MODE_DROPDOWN
108fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
109fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    public Spinner(Context context, int mode) {
110fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell        this(context, null, com.android.internal.R.attr.spinnerStyle, mode);
111fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    }
112fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell
113fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
114fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Construct a new spinner with the given context's theme and the supplied attribute set.
115fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
116fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param context The Context the view is running in, through which it can
117fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        access the current theme, resources, etc.
118fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param attrs The attributes of the XML tag that is inflating the view.
119fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Spinner(Context context, AttributeSet attrs) {
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, attrs, com.android.internal.R.attr.spinnerStyle);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
124fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
125fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Construct a new spinner with the given context's theme, the supplied attribute set,
126fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * and default style.
127fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
128fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param context The Context the view is running in, through which it can
129fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        access the current theme, resources, etc.
130fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param attrs The attributes of the XML tag that is inflating the view.
131fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param defStyle The default style to apply to this view. If 0, no style
132fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        will be applied (beyond what is included in the theme). This may
133fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        either be an attribute resource, whose value will be retrieved
134fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        from the current theme, or an explicit style resource.
135fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Spinner(Context context, AttributeSet attrs, int defStyle) {
137fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell        this(context, attrs, defStyle, MODE_THEME);
138fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    }
139fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell
140fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    /**
141fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * Construct a new spinner with the given context's theme, the supplied attribute set,
142fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * and default style. <code>mode</code> may be one of {@link #MODE_DIALOG} or
143fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * {@link #MODE_DROPDOWN} and determines how the user will select choices from the spinner.
144fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
145fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param context The Context the view is running in, through which it can
146fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        access the current theme, resources, etc.
147fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param attrs The attributes of the XML tag that is inflating the view.
148fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param defStyle The default style to apply to this view. If 0, no style
149fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        will be applied (beyond what is included in the theme). This may
150fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        either be an attribute resource, whose value will be retrieved
151fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *        from the current theme, or an explicit style resource.
152fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @param mode Constant describing how the user will select choices from the spinner.
153fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     *
154fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @see #MODE_DIALOG
155fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     * @see #MODE_DROPDOWN
156fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell     */
157fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell    public Spinner(Context context, AttributeSet attrs, int defStyle, int mode) {
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs, defStyle);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = context.obtainStyledAttributes(attrs,
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.styleable.Spinner, defStyle, 0);
162fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell
163fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell        if (mode == MODE_THEME) {
164fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell            mode = a.getInt(com.android.internal.R.styleable.Spinner_spinnerMode, MODE_DIALOG);
165fef364f75b00e238d28a81e1168bbfc945ce8d23Adam Powell        }
166c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
167c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        switch (mode) {
168c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        case MODE_DIALOG: {
169c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup = new DialogPopup();
170c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            break;
171c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1723f10b1c8f841113b93d2dfecdd84a1dfb1008fafDaisuke Miyakawa
173c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        case MODE_DROPDOWN: {
174a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            DropdownPopup popup = new DropdownPopup(context, attrs, defStyle);
175c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
1768db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell            mDropDownWidth = a.getLayoutDimension(
17772536f7240288485cda81b86985ae26b8bef415fBen Komalo                    com.android.internal.R.styleable.Spinner_dropDownWidth,
1788db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell                    ViewGroup.LayoutParams.WRAP_CONTENT);
179c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            popup.setBackgroundDrawable(a.getDrawable(
180c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    com.android.internal.R.styleable.Spinner_popupBackground));
1818132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            final int verticalOffset = a.getDimensionPixelOffset(
1828132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                    com.android.internal.R.styleable.Spinner_dropDownVerticalOffset, 0);
1838132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            if (verticalOffset != 0) {
1848132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                popup.setVerticalOffset(verticalOffset);
1858132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            }
1868132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell
1878132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            final int horizontalOffset = a.getDimensionPixelOffset(
1888132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                    com.android.internal.R.styleable.Spinner_dropDownHorizontalOffset, 0);
1898132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            if (horizontalOffset != 0) {
1908132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell                popup.setHorizontalOffset(horizontalOffset);
1918132ba5e2e82d02697ef0570142abb8fc8054a67Adam Powell            }
192c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
193c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup = popup;
194c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            break;
195c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
196c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
197c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
198a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        mGravity = a.getInt(com.android.internal.R.styleable.Spinner_gravity, Gravity.CENTER);
199a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell
200c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setPromptText(a.getString(com.android.internal.R.styleable.Spinner_prompt));
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20242b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        mDisableChildrenWhenDisabled = a.getBoolean(
20342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell                com.android.internal.R.styleable.Spinner_disableChildrenWhenDisabled, false);
20442b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
20668464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell
20768464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        // Base constructor can call setAdapter before we initialize mPopup.
20868464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        // Finish setting things up if this happened.
20968464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        if (mTempAdapter != null) {
21068464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell            mPopup.setAdapter(mTempAdapter);
21168464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell            mTempAdapter = null;
21268464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
214a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell
215d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
216d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set the background drawable for the spinner's popup window of choices.
217d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
218d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
219d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @param background Background drawable
220d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
221d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_popupBackground
222d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
223d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setPopupBackgroundDrawable(Drawable background) {
224d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        if (!(mPopup instanceof DropdownPopup)) {
225d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            Log.e(TAG, "setPopupBackgroundDrawable: incompatible spinner mode; ignoring...");
226d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            return;
227d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
228d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        ((DropdownPopup) mPopup).setBackgroundDrawable(background);
229d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
230d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
231d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
232d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set the background drawable for the spinner's popup window of choices.
233d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
234d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
235dca510e026e3e75759bac84c3860dc84b83a608fAdam Powell     * @param resId Resource ID of a background drawable
236d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
237d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_popupBackground
238d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
239d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setPopupBackgroundResource(int resId) {
240d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        setPopupBackgroundDrawable(getContext().getResources().getDrawable(resId));
241d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
242d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
243d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
244d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Get the background drawable for the spinner's popup window of choices.
245d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; other modes will return null.
246d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
247d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @return background Background drawable
248d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
249d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_popupBackground
250d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
251d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public Drawable getPopupBackground() {
252d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        return mPopup.getBackground();
253d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
254d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
255d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
256d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set a vertical offset in pixels for the spinner's popup window of choices.
257d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
258d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
259d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @param pixels Vertical offset in pixels
260d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
261d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
262d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
263d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setDropDownVerticalOffset(int pixels) {
264d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        mPopup.setVerticalOffset(pixels);
265d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
266d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
267d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
268d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Get the configured vertical offset in pixels for the spinner's popup window of choices.
269d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0.
270d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
271d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @return Vertical offset in pixels
272d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
273d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
274d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
275d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public int getDropDownVerticalOffset() {
276d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        return mPopup.getVerticalOffset();
277d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
278d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
279d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
280d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set a horizontal offset in pixels for the spinner's popup window of choices.
281d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
282d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
283d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @param pixels Horizontal offset in pixels
284d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
285d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
286d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
287d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setDropDownHorizontalOffset(int pixels) {
288d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        mPopup.setHorizontalOffset(pixels);
289d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
290d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
291d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
292d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Get the configured horizontal offset in pixels for the spinner's popup window of choices.
293d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0.
294d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
295d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @return Horizontal offset in pixels
296d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
297d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
298d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
299d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public int getDropDownHorizontalOffset() {
300d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        return mPopup.getHorizontalOffset();
301d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
302d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
303d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
304d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Set the width of the spinner's popup window of choices in pixels. This value
305d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * may also be set to {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
306d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * to match the width of the Spinner itself, or
307d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size
308d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * of contained dropdown list items.
309d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
310d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * <p>Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.</p>
311d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
312d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @param pixels Width in pixels, WRAP_CONTENT, or MATCH_PARENT
313d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
314d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownWidth
315d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
316d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public void setDropDownWidth(int pixels) {
317d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        if (!(mPopup instanceof DropdownPopup)) {
318d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            Log.e(TAG, "Cannot set dropdown width for MODE_DIALOG, ignoring");
319d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            return;
320d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
321d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        mDropDownWidth = pixels;
322d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
323d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
324d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
325d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Get the configured width of the spinner's popup window of choices in pixels.
326d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * The returned value may also be {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
327d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * meaning the popup window will match the width of the Spinner itself, or
328d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size
329d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * of contained dropdown list items.
330d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
331d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @return Width in pixels, WRAP_CONTENT, or MATCH_PARENT
332d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
333d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @attr ref android.R.styleable#Spinner_dropDownWidth
334d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
335d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public int getDropDownWidth() {
336d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        return mDropDownWidth;
337d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
338d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
33942b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell    @Override
34042b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell    public void setEnabled(boolean enabled) {
34142b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        super.setEnabled(enabled);
34242b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        if (mDisableChildrenWhenDisabled) {
34342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell            final int count = getChildCount();
34442b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell            for (int i = 0; i < count; i++) {
34542b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell                getChildAt(i).setEnabled(enabled);
34642b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell            }
34742b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        }
34842b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell    }
34942b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell
350a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    /**
351a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     * Describes how the selected item view is positioned. Currently only the horizontal component
352a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     * is used. The default is determined by the current theme.
353a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     *
354a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     * @param gravity See {@link android.view.Gravity}
355a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     *
356a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     * @attr ref android.R.styleable#Spinner_gravity
357a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell     */
358a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    public void setGravity(int gravity) {
359a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        if (mGravity != gravity) {
360a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
36138d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio                gravity |= Gravity.START;
362a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            }
363a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            mGravity = gravity;
364a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            requestLayout();
365a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        }
366a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    }
367a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell
368d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    /**
369d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * Describes how the selected item view is positioned. The default is determined by the
370d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * current theme.
371d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     *
372d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     * @return A {@link android.view.Gravity Gravity} value
373d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell     */
374d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    public int getGravity() {
375d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        return mGravity;
376d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell    }
377d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
378c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    @Override
379c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    public void setAdapter(SpinnerAdapter adapter) {
380c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        super.setAdapter(adapter);
38168464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell
38268464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        if (mPopup != null) {
38368464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell            mPopup.setAdapter(new DropDownAdapter(adapter));
38468464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        } else {
38568464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell            mTempAdapter = new DropDownAdapter(adapter);
38668464a95991d81872a99eefff86a98dd2bd4c8edAdam Powell        }
387c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getBaseline() {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View child = null;
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getChildCount() > 0) {
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child = getChildAt(0);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mAdapter != null && mAdapter.getCount() > 0) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child = makeAndAddView(0);
39722e92e55576e2c723c320824de08d78326379aebAdam Powell            mRecycler.put(0, child);
39822e92e55576e2c723c320824de08d78326379aebAdam Powell            removeAllViewsInLayout();
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (child != null) {
402160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            final int childBaseline = child.getBaseline();
403160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            return childBaseline >= 0 ? child.getTop() + childBaseline : -1;
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return -1;
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4095275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy    @Override
4105275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy    protected void onDetachedFromWindow() {
4115275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy        super.onDetachedFromWindow();
4125275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy
4135275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy        if (mPopup != null && mPopup.isShowing()) {
4145275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy            mPopup.dismiss();
4155275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy        }
4165275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy    }
4175275d69b04aee3f17f698a21d1395e4ba02ac47cRomain Guy
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>A spinner does not support item click events. Calling this method
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * will raise an exception.</p>
4214c359b76f9a030f92a302ba74a528faa170bad4eScott Main     * <p>Instead use {@link AdapterView#setOnItemSelectedListener}.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param l this listener will be ignored
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setOnItemClickListener(OnItemClickListener l) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new RuntimeException("setOnItemClickListener cannot be used with a spinner.");
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
430c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell    /**
431c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell     * @hide internal use only
432c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell     */
433c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell    public void setOnItemClickListenerInt(OnItemClickListener l) {
434c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell        super.setOnItemClickListener(l);
435c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell    }
436c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell
437a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    @Override
438a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
439a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
440a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) {
441a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            final int measuredWidth = getMeasuredWidth();
44219fd164408033eb46a40abd514aa0bf698525e55Adam Powell            setMeasuredDimension(Math.min(Math.max(measuredWidth,
443b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell                    measureContentWidth(getAdapter(), getBackground())),
444b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell                    MeasureSpec.getSize(widthMeasureSpec)),
445a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell                    getMeasuredHeight());
446a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        }
447a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell    }
448a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see android.view.View#onLayout(boolean,int,int,int,int)
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates and positions all views
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onLayout(boolean changed, int l, int t, int r, int b) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onLayout(changed, l, t, r, b);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInLayout = true;
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        layout(0, false);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInLayout = false;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates and positions all views for this Spinner.
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
46638d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio     * @param delta Change in the selected position. +1 means selection is moving to the right,
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so views are scrolling to the left. -1 means selection is moving to the left.
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void layout(int delta, boolean animate) {
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childrenLeft = mSpinnerPadding.left;
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right;
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDataChanged) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handleDataChanged();
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Handle the empty set by removing all views
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mItemCount == 0) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resetList();
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNextSelectedPosition >= 0) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectedPositionInt(mNextSelectedPosition);
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        recycleAllViews();
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Clear out old views
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        removeAllViewsInLayout();
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
493a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        // Make selected view and position it
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = mSelectedPosition;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View sel = makeAndAddView(mSelectedPosition);
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int width = sel.getMeasuredWidth();
497a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        int selectedOffset = childrenLeft;
498e56ffdc7b31b0937628609cc3bbaa15879023569Fabrice Di Meglio        final int layoutDirection = getLayoutDirection();
49938d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
50038d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
501a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            case Gravity.CENTER_HORIZONTAL:
502a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell                selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
503a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell                break;
504a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            case Gravity.RIGHT:
505a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell                selectedOffset = childrenLeft + childrenWidth - width;
506a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell                break;
507a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        }
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sel.offsetLeftAndRight(selectedOffset);
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Flush any cached views that did not get reused above
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRecycler.clear();
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidate();
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkSelectionChanged();
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDataChanged = false;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNeedSync = false;
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setNextSelectedPositionInt(mSelectedPosition);
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtain a view, either by pulling an existing view from the recycler or
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by getting a new one from the adapter. If we are animating, make sure
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * there is enough information in the view's layout parameters to animate
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * from the old to new positions.
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position Position in the spinner for the view to obtain
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A view that has been added to the spinner
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View makeAndAddView(int position) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View child;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mDataChanged) {
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child = mRecycler.get(position);
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (child != null) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Position the view
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setUpChild(child);
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return child;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Nothing found in the recycler -- ask the adapter for a view
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        child = mAdapter.getView(position, null, this);
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Position the view
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setUpChild(child);
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return child;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Helper for makeAndAddView to set the position of a view
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and fill out its layout paramters.
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param child The view to position
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setUpChild(View child) {
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Respect layout params that are already in the view. Otherwise
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // make some up...
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ViewGroup.LayoutParams lp = child.getLayoutParams();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lp == null) {
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            lp = generateDefaultLayoutParams();
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        addViewInLayout(child, 0, lp);
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        child.setSelected(hasFocus());
57242b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        if (mDisableChildrenWhenDisabled) {
57342b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell            child.setEnabled(isEnabled());
57442b7e99b11a5ab1cbc0beebe0b15e46bdf462dffAdam Powell        }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get measure specs
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Measure child
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        child.measure(childWidthSpec, childHeightSpec);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childLeft;
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childRight;
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Position vertically based on gravity setting
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childTop = mSpinnerPadding.top
590189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                + ((getMeasuredHeight() - mSpinnerPadding.bottom -
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        mSpinnerPadding.top - child.getMeasuredHeight()) / 2);
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childBottom = childTop + child.getMeasuredHeight();
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int width = child.getMeasuredWidth();
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childLeft = 0;
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        childRight = childLeft + width;
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        child.layout(childLeft, childTop, childRight, childBottom);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean performClick() {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = super.performClick();
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!handled) {
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            handled = true;
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
608c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (!mPopup.isShowing()) {
609c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                mPopup.show();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return handled;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6158a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onClick(DialogInterface dialog, int which) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setSelection(which);
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        dialog.dismiss();
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6218a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
6228a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6238a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
6248a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(Spinner.class.getName());
6258a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6268a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6278a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
6288a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6298a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
6308a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(Spinner.class.getName());
6318a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
6328a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the prompt to display when the dialog is shown.
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param prompt the prompt to set
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPrompt(CharSequence prompt) {
638c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        mPopup.setPromptText(prompt);
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the prompt to display when the dialog is shown.
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param promptId the resource ID of the prompt to display when the dialog is shown
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPromptId(int promptId) {
646c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        setPrompt(getContext().getText(promptId));
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The prompt to display when the dialog is shown
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public CharSequence getPrompt() {
653c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        return mPopup.getHintText();
654c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
65519fd164408033eb46a40abd514aa0bf698525e55Adam Powell
656b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell    int measureContentWidth(SpinnerAdapter adapter, Drawable background) {
65719fd164408033eb46a40abd514aa0bf698525e55Adam Powell        if (adapter == null) {
65819fd164408033eb46a40abd514aa0bf698525e55Adam Powell            return 0;
65919fd164408033eb46a40abd514aa0bf698525e55Adam Powell        }
66019fd164408033eb46a40abd514aa0bf698525e55Adam Powell
66119fd164408033eb46a40abd514aa0bf698525e55Adam Powell        int width = 0;
66219fd164408033eb46a40abd514aa0bf698525e55Adam Powell        View itemView = null;
66319fd164408033eb46a40abd514aa0bf698525e55Adam Powell        int itemType = 0;
66419fd164408033eb46a40abd514aa0bf698525e55Adam Powell        final int widthMeasureSpec =
66519fd164408033eb46a40abd514aa0bf698525e55Adam Powell            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
66619fd164408033eb46a40abd514aa0bf698525e55Adam Powell        final int heightMeasureSpec =
66719fd164408033eb46a40abd514aa0bf698525e55Adam Powell            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
66819fd164408033eb46a40abd514aa0bf698525e55Adam Powell
66919fd164408033eb46a40abd514aa0bf698525e55Adam Powell        // Make sure the number of items we'll measure is capped. If it's a huge data set
67019fd164408033eb46a40abd514aa0bf698525e55Adam Powell        // with wildly varying sizes, oh well.
671b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        int start = Math.max(0, getSelectedItemPosition());
672b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        final int end = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED);
673b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        final int count = end - start;
674b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        start = Math.max(0, start - (MAX_ITEMS_MEASURED - count));
675b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        for (int i = start; i < end; i++) {
67619fd164408033eb46a40abd514aa0bf698525e55Adam Powell            final int positionType = adapter.getItemViewType(i);
67719fd164408033eb46a40abd514aa0bf698525e55Adam Powell            if (positionType != itemType) {
67819fd164408033eb46a40abd514aa0bf698525e55Adam Powell                itemType = positionType;
67919fd164408033eb46a40abd514aa0bf698525e55Adam Powell                itemView = null;
68019fd164408033eb46a40abd514aa0bf698525e55Adam Powell            }
68119fd164408033eb46a40abd514aa0bf698525e55Adam Powell            itemView = adapter.getView(i, itemView, this);
68219fd164408033eb46a40abd514aa0bf698525e55Adam Powell            if (itemView.getLayoutParams() == null) {
68319fd164408033eb46a40abd514aa0bf698525e55Adam Powell                itemView.setLayoutParams(new ViewGroup.LayoutParams(
68419fd164408033eb46a40abd514aa0bf698525e55Adam Powell                        ViewGroup.LayoutParams.WRAP_CONTENT,
68519fd164408033eb46a40abd514aa0bf698525e55Adam Powell                        ViewGroup.LayoutParams.WRAP_CONTENT));
68619fd164408033eb46a40abd514aa0bf698525e55Adam Powell            }
68719fd164408033eb46a40abd514aa0bf698525e55Adam Powell            itemView.measure(widthMeasureSpec, heightMeasureSpec);
68819fd164408033eb46a40abd514aa0bf698525e55Adam Powell            width = Math.max(width, itemView.getMeasuredWidth());
68919fd164408033eb46a40abd514aa0bf698525e55Adam Powell        }
69019fd164408033eb46a40abd514aa0bf698525e55Adam Powell
69119fd164408033eb46a40abd514aa0bf698525e55Adam Powell        // Add background padding to measured width
692b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell        if (background != null) {
693b70c727b2ec470a091e61100abf05841d59bc9a8Adam Powell            background.getPadding(mTempRect);
69419fd164408033eb46a40abd514aa0bf698525e55Adam Powell            width += mTempRect.left + mTempRect.right;
69519fd164408033eb46a40abd514aa0bf698525e55Adam Powell        }
69619fd164408033eb46a40abd514aa0bf698525e55Adam Powell
69719fd164408033eb46a40abd514aa0bf698525e55Adam Powell        return width;
69819fd164408033eb46a40abd514aa0bf698525e55Adam Powell    }
69919fd164408033eb46a40abd514aa0bf698525e55Adam Powell
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * into a ListAdapter.</p>
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private SpinnerAdapter mAdapter;
7061f09c8314701c1d09be8e350344c58241905677bAdam Powell        private ListAdapter mListAdapter;
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7091f09c8314701c1d09be8e350344c58241905677bAdam Powell         * <p>Creates a new ListAdapter wrapper for the specified adapter.</p>
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @param adapter the Adapter to transform into a ListAdapter
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public DropDownAdapter(SpinnerAdapter adapter) {
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            this.mAdapter = adapter;
7151f09c8314701c1d09be8e350344c58241905677bAdam Powell            if (adapter instanceof ListAdapter) {
7161f09c8314701c1d09be8e350344c58241905677bAdam Powell                this.mListAdapter = (ListAdapter) adapter;
7171f09c8314701c1d09be8e350344c58241905677bAdam Powell            }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getCount() {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAdapter == null ? 0 : mAdapter.getCount();
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Object getItem(int position) {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAdapter == null ? null : mAdapter.getItem(position);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public long getItemId(int position) {
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAdapter == null ? -1 : mAdapter.getItemId(position);
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View getView(int position, View convertView, ViewGroup parent) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getDropDownView(position, convertView, parent);
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public View getDropDownView(int position, View convertView, ViewGroup parent) {
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAdapter == null ? null :
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mAdapter.getDropDownView(position, convertView, parent);
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean hasStableIds() {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mAdapter != null && mAdapter.hasStableIds();
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void registerDataSetObserver(DataSetObserver observer) {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mAdapter != null) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAdapter.registerDataSetObserver(observer);
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void unregisterDataSetObserver(DataSetObserver observer) {
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mAdapter != null) {
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mAdapter.unregisterDataSetObserver(observer);
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7581f09c8314701c1d09be8e350344c58241905677bAdam Powell         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
7591f09c8314701c1d09be8e350344c58241905677bAdam Powell         * Otherwise, return true.
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean areAllItemsEnabled() {
7621f09c8314701c1d09be8e350344c58241905677bAdam Powell            final ListAdapter adapter = mListAdapter;
7631f09c8314701c1d09be8e350344c58241905677bAdam Powell            if (adapter != null) {
7641f09c8314701c1d09be8e350344c58241905677bAdam Powell                return adapter.areAllItemsEnabled();
7651f09c8314701c1d09be8e350344c58241905677bAdam Powell            } else {
7661f09c8314701c1d09be8e350344c58241905677bAdam Powell                return true;
7671f09c8314701c1d09be8e350344c58241905677bAdam Powell            }
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
7711f09c8314701c1d09be8e350344c58241905677bAdam Powell         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
7721f09c8314701c1d09be8e350344c58241905677bAdam Powell         * Otherwise, return true.
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isEnabled(int position) {
7751f09c8314701c1d09be8e350344c58241905677bAdam Powell            final ListAdapter adapter = mListAdapter;
7761f09c8314701c1d09be8e350344c58241905677bAdam Powell            if (adapter != null) {
7771f09c8314701c1d09be8e350344c58241905677bAdam Powell                return adapter.isEnabled(position);
7781f09c8314701c1d09be8e350344c58241905677bAdam Powell            } else {
7791f09c8314701c1d09be8e350344c58241905677bAdam Powell                return true;
7801f09c8314701c1d09be8e350344c58241905677bAdam Powell            }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getItemViewType(int position) {
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getViewTypeCount() {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 1;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public boolean isEmpty() {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return getCount() == 0;
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
795c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
796c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    /**
797c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Implements some sort of popup selection interface for selecting a spinner option.
798c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     * Allows for different spinner modes.
799c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell     */
800c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private interface SpinnerPopup {
801c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void setAdapter(ListAdapter adapter);
802c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
803c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
804c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * Show the popup
805c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
806c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void show();
807c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
808c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
809c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * Dismiss the popup
810c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
811c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void dismiss();
812c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
813c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
814c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @return true if the popup is showing, false otherwise.
815c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
816c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean isShowing();
817c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
818c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        /**
819c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * Set hint text to be displayed to the user. This should provide
820c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * a description of the choice being made.
821c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         * @param hintText Hint text to set.
822c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell         */
823c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void setPromptText(CharSequence hintText);
824c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public CharSequence getHintText();
825d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
826d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setBackgroundDrawable(Drawable bg);
827d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setVerticalOffset(int px);
828d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setHorizontalOffset(int px);
829d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public Drawable getBackground();
830d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public int getVerticalOffset();
831d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public int getHorizontalOffset();
832c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
833c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
834c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener {
835c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private AlertDialog mPopup;
836c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private ListAdapter mListAdapter;
837c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private CharSequence mPrompt;
838c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
839c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void dismiss() {
840c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup.dismiss();
841c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup = null;
842c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
843c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
844c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public boolean isShowing() {
845c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mPopup != null ? mPopup.isShowing() : false;
846c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
847c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
848c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void setAdapter(ListAdapter adapter) {
849c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mListAdapter = adapter;
850c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
851c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
852c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void setPromptText(CharSequence hintText) {
853c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPrompt = hintText;
854c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
855c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
856c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public CharSequence getHintText() {
857c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mPrompt;
858c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
859c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
860c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void show() {
861c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
862c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            if (mPrompt != null) {
863c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                builder.setTitle(mPrompt);
864c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            }
865c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mPopup = builder.setSingleChoiceItems(mListAdapter,
866c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    getSelectedItemPosition(), this).show();
867c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
868c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
869c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void onClick(DialogInterface dialog, int which) {
870c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            setSelection(which);
871c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell            if (mOnItemClickListener != null) {
872c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell                performItemClick(null, which, mListAdapter.getItemId(which));
873c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell            }
874c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            dismiss();
875c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
876d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
877d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
878d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setBackgroundDrawable(Drawable bg) {
879d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            Log.e(TAG, "Cannot set popup background for MODE_DIALOG, ignoring");
880d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
881d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
882d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
883d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setVerticalOffset(int px) {
884d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            Log.e(TAG, "Cannot set vertical offset for MODE_DIALOG, ignoring");
885d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
886d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
887d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
888d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public void setHorizontalOffset(int px) {
889d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            Log.e(TAG, "Cannot set horizontal offset for MODE_DIALOG, ignoring");
890d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
891d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
892d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
893d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public Drawable getBackground() {
894d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            return null;
895d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
896d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
897d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
898d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public int getVerticalOffset() {
899d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            return 0;
900d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
901d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell
902d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        @Override
903d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        public int getHorizontalOffset() {
904d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell            return 0;
905d9c7be6cc7d18f11731e6d7a1037cc294fde3a4bAdam Powell        }
906c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
907c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
908c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    private class DropdownPopup extends ListPopupWindow implements SpinnerPopup {
909c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        private CharSequence mHintText;
91019fd164408033eb46a40abd514aa0bf698525e55Adam Powell        private ListAdapter mAdapter;
911efd0811a31e79aa1d3ee6fcaf8d79304872fcc5eChris Yerga
912a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell        public DropdownPopup(Context context, AttributeSet attrs, int defStyleRes) {
913c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            super(context, attrs, 0, defStyleRes);
91450f784cf2dc2dea8061153ac3a843f60a9d88781Adam Powell
915c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            setAnchorView(Spinner.this);
916c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            setModal(true);
917be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell            setPromptPosition(POSITION_PROMPT_ABOVE);
918c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            setOnItemClickListener(new OnItemClickListener() {
919c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                public void onItemClick(AdapterView parent, View v, int position, long id) {
920c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    Spinner.this.setSelection(position);
921c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell                    if (mOnItemClickListener != null) {
922af3631314f3d9423a3bd77f9cbaea16207b2aff8Adam Powell                        Spinner.this.performItemClick(v, position, mAdapter.getItemId(position));
923c4e57e23f99f4cea6fcca870a95f7f20a6edfaf2Adam Powell                    }
924c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                    dismiss();
925c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell                }
926c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            });
927c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
928c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
92919fd164408033eb46a40abd514aa0bf698525e55Adam Powell        @Override
93019fd164408033eb46a40abd514aa0bf698525e55Adam Powell        public void setAdapter(ListAdapter adapter) {
93119fd164408033eb46a40abd514aa0bf698525e55Adam Powell            super.setAdapter(adapter);
93219fd164408033eb46a40abd514aa0bf698525e55Adam Powell            mAdapter = adapter;
93319fd164408033eb46a40abd514aa0bf698525e55Adam Powell        }
93419fd164408033eb46a40abd514aa0bf698525e55Adam Powell
935c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public CharSequence getHintText() {
936c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            return mHintText;
937c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
938c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell
939c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void setPromptText(CharSequence hintText) {
940a39b987bb761899636ae1e3669d1343499d04ebdAdam Powell            // Hint text is ignored for dropdowns, but maintain it here.
941c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            mHintText = hintText;
942c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
9433f10b1c8f841113b93d2dfecdd84a1dfb1008fafDaisuke Miyakawa
9443f10b1c8f841113b93d2dfecdd84a1dfb1008fafDaisuke Miyakawa        @Override
945c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        public void show() {
94695148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park            final Drawable background = getBackground();
94738d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            int hOffset = 0;
94895148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park            if (background != null) {
94995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                background.getPadding(mTempRect);
95038d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio                hOffset = isLayoutRtl() ? mTempRect.right : -mTempRect.left;
95195148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park            } else {
95295148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                mTempRect.left = mTempRect.right = 0;
95395148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park            }
95495148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park
95562e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell            final int spinnerPaddingLeft = Spinner.this.getPaddingLeft();
95638d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            final int spinnerPaddingRight = Spinner.this.getPaddingRight();
95738d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            final int spinnerWidth = Spinner.this.getWidth();
9588db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell            if (mDropDownWidth == WRAP_CONTENT) {
95995148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                int contentWidth =  measureContentWidth(
96095148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                        (SpinnerAdapter) mAdapter, getBackground());
96195148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                final int contentWidthLimit = mContext.getResources()
96295148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                        .getDisplayMetrics().widthPixels - mTempRect.left - mTempRect.right;
96395148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                if (contentWidth > contentWidthLimit) {
96495148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                    contentWidth = contentWidthLimit;
96595148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                }
96662e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell                setContentWidth(Math.max(
96795148495fc3d33e4ad4dcbdee83317422db94dbfSeongJae Park                       contentWidth, spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight));
9688db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell            } else if (mDropDownWidth == MATCH_PARENT) {
96962e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell                setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight);
9708db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell            } else {
97162e2bdecc21819a71c04204f20fc051886fdabd6Adam Powell                setContentWidth(mDropDownWidth);
9728db7cb1cdfd357730c641bd1d858f3b1495d9a68Adam Powell            }
97338d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio
97438d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            if (isLayoutRtl()) {
97538d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio                hOffset += spinnerWidth - spinnerPaddingRight - getWidth();
97638d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            } else {
97738d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio                hOffset += spinnerPaddingLeft;
97838d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            }
97938d64c5a95183f2574422a8e8c32c8ae3b96c4f3Fabrice Di Meglio            setHorizontalOffset(hOffset);
9806f5e934b96c400f610b1c5ad228cc60cab5d443fAdam Powell            setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
981c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            super.show();
982c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
983c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell            setSelection(Spinner.this.getSelectedItemPosition());
984f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell
985f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            // Make sure we hide if our anchor goes away.
986f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            // TODO: This might be appropriate to push all the way down to PopupWindow,
987f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            // but it may have other side effects to investigate first. (Text editing handles, etc.)
988f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            final ViewTreeObserver vto = getViewTreeObserver();
989f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            if (vto != null) {
990f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                final OnGlobalLayoutListener layoutListener = new OnGlobalLayoutListener() {
991f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                    @Override
992f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                    public void onGlobalLayout() {
993f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                        if (!Spinner.this.isVisibleToUser()) {
994f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                            dismiss();
995f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                        }
996f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                    }
997f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                };
998f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                vto.addOnGlobalLayoutListener(layoutListener);
999f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                setOnDismissListener(new OnDismissListener() {
1000f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                    @Override public void onDismiss() {
1001f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                        final ViewTreeObserver vto = getViewTreeObserver();
1002f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                        if (vto != null) {
1003f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                            vto.removeOnGlobalLayoutListener(layoutListener);
1004f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                        }
1005f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                    }
1006f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell                });
1007f16daf61275de8bb59a0761d5dabc222ce249946Adam Powell            }
1008c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell        }
1009c3fa6304c997ccecf8ed15a4cbb7bd245128f3c3Adam Powell    }
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1011