179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes/*
279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Copyright (C) 2007 The Android Open Source Project
379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * you may not use this file except in compliance with the License.
679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * You may obtain a copy of the License at
779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
1079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Unless required by applicable law or agreed to in writing, software
1179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * See the License for the specific language governing permissions and
1479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * limitations under the License.
1579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes */
1679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
17b79bd8bd1afdf165068ddafdc5fa0667f7ec4a70Jeff Brownpackage android.support.v7.internal.widget;
18b79bd8bd1afdf165068ddafdc5fa0667f7ec4a70Jeff Brown
1979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.app.AlertDialog;
2079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.content.Context;
2179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.content.DialogInterface;
2279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.content.DialogInterface.OnClickListener;
2379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.content.res.TypedArray;
2479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.database.DataSetObserver;
2579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.graphics.Rect;
2679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.graphics.drawable.Drawable;
27da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
2879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.util.AttributeSet;
2979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.Gravity;
3079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.View;
3179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.ViewGroup;
3279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.AdapterView;
3379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.ListAdapter;
3479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.ListView;
3579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.SpinnerAdapter;
3679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
3779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
3879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes/**
3979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * A view that displays one child at a time and lets the user pick among them.
4079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * The items in the Spinner come from the {@link android.widget.Adapter} associated with
4179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * this view.
4279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
4379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Spinner
4479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * tutorial</a>.</p>
4579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
46b79bd8bd1afdf165068ddafdc5fa0667f7ec4a70Jeff Brown * @attr ref android.support.v7.appcompat.R.styleable#Spinner_prompt
4779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes */
4879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesclass SpinnerICS extends AbsSpinnerICS implements OnClickListener {
4979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private static final String TAG = "Spinner";
5079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
5179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    // Only measure this many items to get a decent max width.
5279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private static final int MAX_ITEMS_MEASURED = 15;
5379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
5479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
5579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Use a dialog window for selecting spinner options.
5679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
5779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int MODE_DIALOG = 0;
5879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
5979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
6079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Use a dropdown anchored to the Spinner for selecting spinner options.
6179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
6279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int MODE_DROPDOWN = 1;
6379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
6479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
6579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Use the theme-supplied value to select the dropdown mode.
6679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
6779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private static final int MODE_THEME = -1;
6879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
6979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private SpinnerPopup mPopup;
7079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private DropDownAdapter mTempAdapter;
7179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mDropDownWidth;
7279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
7379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private int mGravity;
7479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
7579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private Rect mTempRect = new Rect();
7679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
7779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
7879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Construct a new spinner with the given context's theme.
7979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
8079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param context The Context the view is running in, through which it can
8179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        access the current theme, resources, etc.
8279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
8379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    SpinnerICS(Context context) {
8479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        this(context, null);
8579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
8679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
8779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
8879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Construct a new spinner with the given context's theme and the supplied
8979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * mode of displaying choices. <code>mode</code> may be one of
9079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * {@link #MODE_DIALOG} or {@link #MODE_DROPDOWN}.
9179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
9279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param context The Context the view is running in, through which it can
9379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        access the current theme, resources, etc.
9479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param mode Constant describing how the user will select choices from the spinner.
9579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
9679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #MODE_DIALOG
9779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #MODE_DROPDOWN
9879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
9979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    SpinnerICS(Context context, int mode) {
10079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        this(context, null, R.attr.spinnerStyle, mode);
10179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
10279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
10379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
10479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Construct a new spinner with the given context's theme and the supplied attribute set.
10579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
10679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param context The Context the view is running in, through which it can
10779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        access the current theme, resources, etc.
10879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param attrs The attributes of the XML tag that is inflating the view.
10979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
11079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    SpinnerICS(Context context, AttributeSet attrs) {
11179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        this(context, attrs, R.attr.spinnerStyle);
11279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
11379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
11479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
11579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Construct a new spinner with the given context's theme, the supplied attribute set,
11679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * and default style.
11779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
11879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param context The Context the view is running in, through which it can
11979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        access the current theme, resources, etc.
12079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param attrs The attributes of the XML tag that is inflating the view.
12179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param defStyle The default style to apply to this view. If 0, no style
12279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        will be applied (beyond what is included in the theme). This may
12379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        either be an attribute resource, whose value will be retrieved
12479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        from the current theme, or an explicit style resource.
12579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
12679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    SpinnerICS(Context context, AttributeSet attrs, int defStyle) {
12779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        this(context, attrs, defStyle, MODE_THEME);
12879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
12979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
13079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
13179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Construct a new spinner with the given context's theme, the supplied attribute set,
13279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * and default style. <code>mode</code> may be one of {@link #MODE_DIALOG} or
13379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * {@link #MODE_DROPDOWN} and determines how the user will select choices from the spinner.
13479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
13579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param context The Context the view is running in, through which it can
13679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        access the current theme, resources, etc.
13779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param attrs The attributes of the XML tag that is inflating the view.
13879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param defStyle The default style to apply to this view. If 0, no style
13979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        will be applied (beyond what is included in the theme). This may
14079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        either be an attribute resource, whose value will be retrieved
14179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        from the current theme, or an explicit style resource.
14279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param mode Constant describing how the user will select choices from the spinner.
14379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
14479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #MODE_DIALOG
14579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #MODE_DROPDOWN
14679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
14779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    SpinnerICS(Context context, AttributeSet attrs, int defStyle, int mode) {
14879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super(context, attrs, defStyle);
14979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
15079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        TypedArray a = context.obtainStyledAttributes(attrs,
15179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                R.styleable.Spinner, defStyle, 0);
15279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
15379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mode == MODE_THEME) {
15479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mode = a.getInt(R.styleable.Spinner_spinnerMode, MODE_DIALOG);
15579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
15679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
15779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        switch (mode) {
15879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            case MODE_DIALOG: {
15979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mPopup = new DialogPopup();
16079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                break;
16179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
16279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
16379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            case MODE_DROPDOWN: {
16479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                DropdownPopup popup = new DropdownPopup(context, attrs, defStyle);
16579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
16679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mDropDownWidth = a.getLayoutDimension(R.styleable.Spinner_android_dropDownWidth,
16779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        ViewGroup.LayoutParams.WRAP_CONTENT);
16879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
16979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                popup.setBackgroundDrawable(
17079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        a.getDrawable(R.styleable.Spinner_android_popupBackground));
17179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
17279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int verticalOffset = a.getDimensionPixelOffset(
17379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        R.styleable.Spinner_android_dropDownVerticalOffset, 0);
17479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (verticalOffset != 0) {
17579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    popup.setVerticalOffset(verticalOffset);
17679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
17779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
17879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int horizontalOffset = a.getDimensionPixelOffset(
17979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        R.styleable.Spinner_android_dropDownHorizontalOffset, 0);
18079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (horizontalOffset != 0) {
18179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    popup.setHorizontalOffset(horizontalOffset);
18279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
18379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
18479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mPopup = popup;
18579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                break;
18679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
18779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
18879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
18979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mGravity = a.getInt(R.styleable.Spinner_android_gravity, Gravity.CENTER);
19079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
19179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mPopup.setPromptText(a.getString(R.styleable.Spinner_prompt));
19279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
19379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        a.recycle();
19479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
19579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Base constructor can call setAdapter before we initialize mPopup.
19679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Finish setting things up if this happened.
19779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mTempAdapter != null) {
19879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup.setAdapter(mTempAdapter);
19979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mTempAdapter = null;
20079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
20179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
20279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
20379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
20479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Describes how the selected item view is positioned. Currently only the horizontal component
20579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * is used. The default is determined by the current theme.
20679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
20779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param gravity See {@link android.view.Gravity}
20879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
20979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @attr ref android.R.styleable#Spinner_gravity
21079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
21179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setGravity(int gravity) {
21279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mGravity != gravity) {
21379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == 0) {
21479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                gravity |= Gravity.LEFT;
21579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
21679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mGravity = gravity;
21779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            requestLayout();
21879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
21979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
22079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
22179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
22279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setAdapter(SpinnerAdapter adapter) {
22379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.setAdapter(adapter);
22479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
22579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mPopup != null) {
22679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup.setAdapter(new DropDownAdapter(adapter));
22779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else {
22879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mTempAdapter = new DropDownAdapter(adapter);
22979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
23079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
23179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
23279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
23379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getBaseline() {
23479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View child = null;
23579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
23679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (getChildCount() > 0) {
23779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            child = getChildAt(0);
23879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else if (mAdapter != null && mAdapter.getCount() > 0) {
23979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            child = makeAndAddView(0);
24079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mRecycler.put(0, child);
24179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            removeAllViewsInLayout();
24279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
24379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
24479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (child != null) {
24579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final int childBaseline = child.getBaseline();
24679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return childBaseline >= 0 ? child.getTop() + childBaseline : -1;
24779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else {
24879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return -1;
24979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
25079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
25179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
25279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
25379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void onDetachedFromWindow() {
25479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.onDetachedFromWindow();
25579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
25679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mPopup != null && mPopup.isShowing()) {
25779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup.dismiss();
25879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
25979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
26079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
26179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
26279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * <p>A spinner does not support item click events. Calling this method
26379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * will raise an exception.</p>
26479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
26579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param l this listener will be ignored
26679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
26779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
26879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setOnItemClickListener(OnItemClickListener l) {
26979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new RuntimeException("setOnItemClickListener cannot be used with a spinner.");
27079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
27179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
272449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes    void setOnItemClickListenerInt(OnItemClickListener l) {
273449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes        super.setOnItemClickListener(l);
274449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes    }
275449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes
27679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
27779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
27879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
27979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mPopup != null && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) {
28079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final int measuredWidth = getMeasuredWidth();
28179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setMeasuredDimension(Math.min(Math.max(measuredWidth,
28279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    measureContentWidth(getAdapter(), getBackground())),
28379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    MeasureSpec.getSize(widthMeasureSpec)),
28479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    getMeasuredHeight());
28579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
28679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
28779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
28879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
28979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see android.view.View#onLayout(boolean,int,int,int,int)
29079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
29179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Creates and positions all views
29279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
29379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
29479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
29579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void onLayout(boolean changed, int l, int t, int r, int b) {
29679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.onLayout(changed, l, t, r, b);
29779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mInLayout = true;
29879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        layout(0, false);
29979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mInLayout = false;
30079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
30179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
30279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
30379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Creates and positions all views for this Spinner.
30479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
30579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param delta Change in the selected position. +1 moves selection is moving to the right,
30679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * so views are scrolling to the left. -1 means selection is moving to the left.
30779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
30879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
30979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void layout(int delta, boolean animate) {
31079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childrenLeft = mSpinnerPadding.left;
31179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childrenWidth = getRight() - getLeft() - mSpinnerPadding.left - mSpinnerPadding.right;
31279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
31379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mDataChanged) {
31479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            handleDataChanged();
31579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
31679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
31779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Handle the empty set by removing all views
31879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mItemCount == 0) {
31979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            resetList();
32079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return;
32179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
32279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
32379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mNextSelectedPosition >= 0) {
32479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setSelectedPositionInt(mNextSelectedPosition);
32579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
32679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
32779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        recycleAllViews();
32879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
32979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Clear out old views
33079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        removeAllViewsInLayout();
33179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
33279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Make selected view and position it
33379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mFirstPosition = mSelectedPosition;
33479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View sel = makeAndAddView(mSelectedPosition);
33579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int width = sel.getMeasuredWidth();
33679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int selectedOffset = childrenLeft;
33779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
33879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            case Gravity.CENTER_HORIZONTAL:
33979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                selectedOffset = childrenLeft + (childrenWidth / 2) - (width / 2);
34079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                break;
34179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            case Gravity.RIGHT:
34279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                selectedOffset = childrenLeft + childrenWidth - width;
34379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                break;
34479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
34579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        sel.offsetLeftAndRight(selectedOffset);
34679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
34779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Flush any cached views that did not get reused above
34879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mRecycler.clear();
34979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        invalidate();
35179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        checkSelectionChanged();
35379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mDataChanged = false;
35579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mNeedSync = false;
35679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        setNextSelectedPositionInt(mSelectedPosition);
35779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
35879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
36079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Obtain a view, either by pulling an existing view from the recycler or
36179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * by getting a new one from the adapter. If we are animating, make sure
36279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * there is enough information in the view's layout parameters to animate
36379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * from the old to new positions.
36479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
36579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position Position in the spinner for the view to obtain
36679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return A view that has been added to the spinner
36779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
36879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private View makeAndAddView(int position) {
36979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
37079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View child;
37179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
37279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (!mDataChanged) {
37379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            child = mRecycler.get(position);
37479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (child != null) {
37579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Position the view
37679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setUpChild(child);
37779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
37879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return child;
37979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
38079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
38179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
38279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Nothing found in the recycler -- ask the adapter for a view
38379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        child = mAdapter.getView(position, null, this);
38479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
38579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Position the view
38679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        setUpChild(child);
38779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
38879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return child;
38979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
39079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
39179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
39279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Helper for makeAndAddView to set the position of a view
39379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * and fill out its layout paramters.
39479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
39579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child The view to position
39679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
39779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private void setUpChild(View child) {
39879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
39979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Respect layout params that are already in the view. Otherwise
40079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // make some up...
40179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        ViewGroup.LayoutParams lp = child.getLayoutParams();
40279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (lp == null) {
40379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            lp = generateDefaultLayoutParams();
40479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
40579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
40679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        addViewInLayout(child, 0, lp);
40779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
40879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        child.setSelected(hasFocus());
40979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
41079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Get measure specs
41179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childHeightSpec = ViewGroup.getChildMeasureSpec(mHeightMeasureSpec,
41279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSpinnerPadding.top + mSpinnerPadding.bottom, lp.height);
41379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec,
41479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSpinnerPadding.left + mSpinnerPadding.right, lp.width);
41579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
41679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Measure child
41779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        child.measure(childWidthSpec, childHeightSpec);
41879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
41979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childLeft;
42079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childRight;
42179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
42279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Position vertically based on gravity setting
42379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childTop = mSpinnerPadding.top
42479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                + ((getMeasuredHeight() - mSpinnerPadding.bottom -
42579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSpinnerPadding.top - child.getMeasuredHeight()) / 2);
42679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int childBottom = childTop + child.getMeasuredHeight();
42779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
42879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int width = child.getMeasuredWidth();
42979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        childLeft = 0;
43079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        childRight = childLeft + width;
43179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
43279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        child.layout(childLeft, childTop, childRight, childBottom);
43379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
43479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
43579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
43679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public boolean performClick() {
43779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean handled = super.performClick();
43879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
43979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (!handled) {
44079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            handled = true;
44179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
44279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (!mPopup.isShowing()) {
44379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mPopup.show();
44479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
44579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
44679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
44779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return handled;
44879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
44979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
45079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void onClick(DialogInterface dialog, int which) {
45179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        setSelection(which);
45279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        dialog.dismiss();
45379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
45479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
45579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
45679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sets the prompt to display when the dialog is shown.
45779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param prompt the prompt to set
45879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
45979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setPrompt(CharSequence prompt) {
46079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mPopup.setPromptText(prompt);
46179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
46279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
46379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
46479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sets the prompt to display when the dialog is shown.
46579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param promptId the resource ID of the prompt to display when the dialog is shown
46679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
46779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setPromptId(int promptId) {
46879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        setPrompt(getContext().getText(promptId));
46979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
47079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
47179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
47279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The prompt to display when the dialog is shown
47379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
47479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public CharSequence getPrompt() {
47579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mPopup.getHintText();
47679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
47779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
47879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int measureContentWidth(SpinnerAdapter adapter, Drawable background) {
47979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (adapter == null) {
48079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return 0;
48179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
48279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
48379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int width = 0;
48479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View itemView = null;
48579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int itemType = 0;
48679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int widthMeasureSpec =
48779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
48879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int heightMeasureSpec =
48979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
49079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
49179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Make sure the number of items we'll measure is capped. If it's a huge data set
49279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // with wildly varying sizes, oh well.
49379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int start = Math.max(0, getSelectedItemPosition());
49479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int end = Math.min(adapter.getCount(), start + MAX_ITEMS_MEASURED);
49579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int count = end - start;
49679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        start = Math.max(0, start - (MAX_ITEMS_MEASURED - count));
49779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        for (int i = start; i < end; i++) {
49879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final int positionType = adapter.getItemViewType(i);
49979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (positionType != itemType) {
50079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                itemType = positionType;
50179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                itemView = null;
50279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
50379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            itemView = adapter.getView(i, itemView, this);
50479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (itemView.getLayoutParams() == null) {
50579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                itemView.setLayoutParams(new ViewGroup.LayoutParams(
50679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        ViewGroup.LayoutParams.WRAP_CONTENT,
50779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        ViewGroup.LayoutParams.WRAP_CONTENT));
50879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
50979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            itemView.measure(widthMeasureSpec, heightMeasureSpec);
51079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            width = Math.max(width, itemView.getMeasuredWidth());
51179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
51279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
51379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Add background padding to measured width
51479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (background != null) {
51579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            background.getPadding(mTempRect);
51679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            width += mTempRect.left + mTempRect.right;
51779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
51879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
51979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return width;
52079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
52179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
52279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
52379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance
52479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * into a ListAdapter.</p>
52579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
52679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
52779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private SpinnerAdapter mAdapter;
52879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private ListAdapter mListAdapter;
52979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
53079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
53179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * <p>Creates a new ListAdapter wrapper for the specified adapter.</p>
53279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
53379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param adapter the Adapter to transform into a ListAdapter
53479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
53579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public DropDownAdapter(SpinnerAdapter adapter) {
53679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            this.mAdapter = adapter;
53779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (adapter instanceof ListAdapter) {
53879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                this.mListAdapter = (ListAdapter) adapter;
53979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
54079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
54179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
54279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public int getCount() {
54379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mAdapter == null ? 0 : mAdapter.getCount();
54479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
54579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
54679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public Object getItem(int position) {
54779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mAdapter == null ? null : mAdapter.getItem(position);
54879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
54979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
55079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public long getItemId(int position) {
55179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mAdapter == null ? -1 : mAdapter.getItemId(position);
55279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
55379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
55479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public View getView(int position, View convertView, ViewGroup parent) {
55579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return getDropDownView(position, convertView, parent);
55679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
55779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
55879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public View getDropDownView(int position, View convertView, ViewGroup parent) {
55979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mAdapter == null ? null :
56079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mAdapter.getDropDownView(position, convertView, parent);
56179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
56279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
56379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean hasStableIds() {
56479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mAdapter != null && mAdapter.hasStableIds();
56579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
56679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
56779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void registerDataSetObserver(DataSetObserver observer) {
56879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mAdapter != null) {
56979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mAdapter.registerDataSetObserver(observer);
57079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
57179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
57279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
57379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void unregisterDataSetObserver(DataSetObserver observer) {
57479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mAdapter != null) {
57579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mAdapter.unregisterDataSetObserver(observer);
57679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
57779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
57879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
57979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
58079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
58179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Otherwise, return true.
58279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
58379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean areAllItemsEnabled() {
58479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final ListAdapter adapter = mListAdapter;
58579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (adapter != null) {
58679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return adapter.areAllItemsEnabled();
58779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
58879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return true;
58979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
59079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
59179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
59279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
59379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * If the wrapped SpinnerAdapter is also a ListAdapter, delegate this call.
59479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Otherwise, return true.
59579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
59679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean isEnabled(int position) {
59779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final ListAdapter adapter = mListAdapter;
59879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (adapter != null) {
59979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return adapter.isEnabled(position);
60079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
60179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return true;
60279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
60379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
60479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
60579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public int getItemViewType(int position) {
60679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return 0;
60779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
60879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
60979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public int getViewTypeCount() {
61079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return 1;
61179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
61279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
61379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean isEmpty() {
61479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return getCount() == 0;
61579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
61679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
61779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
61879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
61979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Implements some sort of popup selection interface for selecting a spinner option.
62079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Allows for different spinner modes.
62179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
62279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private interface SpinnerPopup {
62379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setAdapter(ListAdapter adapter);
62479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
62579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
62679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Show the popup
62779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
62879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void show();
62979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
63079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
63179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Dismiss the popup
63279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
63379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void dismiss();
63479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
63579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
63679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @return true if the popup is showing, false otherwise.
63779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
63879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean isShowing();
63979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
64079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
64179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Set hint text to be displayed to the user. This should provide
64279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * a description of the choice being made.
64379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param hintText Hint text to set.
64479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
64579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setPromptText(CharSequence hintText);
64679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public CharSequence getHintText();
64779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
64879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
64979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener {
65079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private AlertDialog mPopup;
65179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private ListAdapter mListAdapter;
65279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private CharSequence mPrompt;
65379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
65479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void dismiss() {
65579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup.dismiss();
65679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup = null;
65779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
65879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
65979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public boolean isShowing() {
66079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mPopup != null ? mPopup.isShowing() : false;
66179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
66279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
66379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setAdapter(ListAdapter adapter) {
66479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mListAdapter = adapter;
66579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
66679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
66779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setPromptText(CharSequence hintText) {
66879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPrompt = hintText;
66979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
67079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
67179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public CharSequence getHintText() {
67279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mPrompt;
67379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
67479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
67579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void show() {
67679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
67779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mPrompt != null) {
67879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                builder.setTitle(mPrompt);
67979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
68079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mPopup = builder.setSingleChoiceItems(mListAdapter,
68179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    getSelectedItemPosition(), this).show();
68279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
68379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
68479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void onClick(DialogInterface dialog, int which) {
68579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setSelection(which);
686449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes            if (mOnItemClickListener != null) {
687449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes                performItemClick(null, which, mListAdapter.getItemId(which));
688449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes            }
68979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            dismiss();
69079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
69179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
69279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
693da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brown    private class DropdownPopup extends android.support.v7.internal.widget.ListPopupWindow
69479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            implements SpinnerPopup {
69579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private CharSequence mHintText;
69679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private ListAdapter mAdapter;
69779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
69879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public DropdownPopup(Context context, AttributeSet attrs, int defStyleRes) {
69979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            super(context, attrs, defStyleRes);
70079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
70179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setAnchorView(SpinnerICS.this);
70279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setModal(true);
70379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setPromptPosition(POSITION_PROMPT_ABOVE);
70479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
70579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            AdapterView.OnItemClickListener listener = new OnItemClickListenerWrapper(
70679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    new OnItemClickListener() {
70779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                public void onItemClick(AdapterViewICS parent, View v, int position, long id) {
70879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    SpinnerICS.this.setSelection(position);
709449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes                    if (mOnItemClickListener != null) {
710449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes                        SpinnerICS.this.performItemClick(v, position, mAdapter.getItemId(position));
711449ba8fe7056873134b0ee02ad5acb615bc7d249Chris Banes                    }
71279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    dismiss();
71379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
71479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            });
71579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
71679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setOnItemClickListener(listener);
71779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
71879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
71979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        @Override
72079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setAdapter(ListAdapter adapter) {
72179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            super.setAdapter(adapter);
72279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mAdapter = adapter;
72379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
72479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
72579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public CharSequence getHintText() {
72679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return mHintText;
72779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
72879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
72979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void setPromptText(CharSequence hintText) {
73079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Hint text is ignored for dropdowns, but maintain it here.
73179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mHintText = hintText;
73279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
73379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
73479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        @Override
73579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void show() {
73679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final int spinnerPaddingLeft = SpinnerICS.this.getPaddingLeft();
73779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mDropDownWidth == WRAP_CONTENT) {
73879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int spinnerWidth = SpinnerICS.this.getWidth();
73979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int spinnerPaddingRight = SpinnerICS.this.getPaddingRight();
74079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setContentWidth(Math.max(
74179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        measureContentWidth((SpinnerAdapter) mAdapter, getBackground()),
74279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight));
74379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else if (mDropDownWidth == FILL_PARENT) {
74479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int spinnerWidth = SpinnerICS.this.getWidth();
74579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                final int spinnerPaddingRight = SpinnerICS.this.getPaddingRight();
74679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setContentWidth(spinnerWidth - spinnerPaddingLeft - spinnerPaddingRight);
74779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
74879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setContentWidth(mDropDownWidth);
74979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
75079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            final Drawable background = getBackground();
75179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            int bgOffset = 0;
75279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (background != null) {
75379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                background.getPadding(mTempRect);
75479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                bgOffset = -mTempRect.left;
75579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
75679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setHorizontalOffset(bgOffset + spinnerPaddingLeft);
75779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
75879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            super.show();
75979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
76079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setSelection(SpinnerICS.this.getSelectedItemPosition());
76179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
76279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
76379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes}
764