Як зробити Android Spinner з початковим текстом "Вибрати один"?


569

Я хочу використовувати Spinner, який спочатку (коли користувач ще не здійснив вибір) відображає текст "Вибрати один". Коли користувач натискає на спінер, відображається список елементів, і користувач вибирає один із варіантів. Після того, як користувач здійснив вибір, вибраний елемент відображається у спинарі замість "Вибрати один".

У мене є такий код, щоб створити Spinner:

String[] items = new String[] {"One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

За допомогою цього коду спочатку відображається пункт "Один". Я міг би просто додати новий елемент "Вибрати один" до елементів, але потім "Вибрати один" також буде показаний у випадаючому списку як перший елемент, який не є тим, що я хочу.

Як я можу виправити цю проблему?


6
Ідеальне рішення лежить в цьому питанні: stackoverflow.com/questions/9863378 / ... Просто перевизначити метод getDropDownView ().
Сураб Шарма

Ви намагалися встановити перший елемент адаптера на "Вибрати один"?
ІгорГанапольський

[Тут інше відмінне рішення добре!] [1] [1]: stackoverflow.com/questions/9863378 / ...
AirtonCarneiro

багаторазовий спінер
HenryChuang

android--code.blogspot.in/2015/08/android-spinner-hint.html ще один хороший підручник
Prabs

Відповіді:


255

Ось загальне рішення, яке перекриває Spinnerперегляд. Він переосмислює setAdapter()встановлення початкового положення на -1 і надає проксі-сервер, що постачається, SpinnerAdapterдля відображення рядка-підказки для позиції менше 0.

Це було перевірено на Android 1.5 - 4.2, але будьте обачні! Оскільки це рішення покладається на роздум над тим, щоб викликати приватне, AdapterView.setNextSelectedPositionInt()і AdapterView.setSelectedPositionInt()це не гарантовано працювати в майбутніх оновленнях ОС. Здається, це буде, але це аж ніяк не гарантується.

Зазвичай я б не погодився на щось подібне, але це питання було задано достатньо разів, і, здається, це досить розумний запит, який я думав, що опублікую своє рішення.

/**
 * A modified Spinner that doesn't automatically select the first entry in the list.
 *
 * Shows the prompt if nothing is selected.
 *
 * Limitations: does not display prompt if the entry list is empty.
 */
public class NoDefaultSpinner extends Spinner {

    public NoDefaultSpinner(Context context) {
        super(context);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NoDefaultSpinner(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setAdapter(SpinnerAdapter orig ) {
        final SpinnerAdapter adapter = newProxy(orig);

        super.setAdapter(adapter);

        try {
            final Method m = AdapterView.class.getDeclaredMethod(
                               "setNextSelectedPositionInt",int.class);
            m.setAccessible(true);
            m.invoke(this,-1);

            final Method n = AdapterView.class.getDeclaredMethod(
                               "setSelectedPositionInt",int.class);
            n.setAccessible(true);
            n.invoke(this,-1);
        } 
        catch( Exception e ) {
            throw new RuntimeException(e);
        }
    }

    protected SpinnerAdapter newProxy(SpinnerAdapter obj) {
        return (SpinnerAdapter) java.lang.reflect.Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                new Class[]{SpinnerAdapter.class},
                new SpinnerAdapterProxy(obj));
    }



    /**
     * Intercepts getView() to display the prompt if position < 0
     */
    protected class SpinnerAdapterProxy implements InvocationHandler {

        protected SpinnerAdapter obj;
        protected Method getView;


        protected SpinnerAdapterProxy(SpinnerAdapter obj) {
            this.obj = obj;
            try {
                this.getView = SpinnerAdapter.class.getMethod(
                                 "getView",int.class,View.class,ViewGroup.class);
            } 
            catch( Exception e ) {
                throw new RuntimeException(e);
            }
        }

        public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
            try {
                return m.equals(getView) && 
                       (Integer)(args[0])<0 ? 
                         getView((Integer)args[0],(View)args[1],(ViewGroup)args[2]) : 
                         m.invoke(obj, args);
            } 
            catch (InvocationTargetException e) {
                throw e.getTargetException();
            } 
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        protected View getView(int position, View convertView, ViewGroup parent) 
          throws IllegalAccessException {

            if( position<0 ) {
                final TextView v = 
                  (TextView) ((LayoutInflater)getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE)).inflate(
                      android.R.layout.simple_spinner_item,parent,false);
                v.setText(getPrompt());
                return v;
            }
            return obj.getView(position,convertView,parent);
        }
    }
}

7
@emmby У вас є ідеї, як очистити вибір після того, як користувач встановив його? Я спробував рефакторинг двох викликів invoke () на метод clearSelection (), але він насправді не працює. Хоча спливаючий список показує раніше вибраний елемент як невибраний, віджет спінера все одно показує його як вибраний, і якщо користувач вибирає той самий елемент знову, onItemSelected () не викликається.
Qwertie

3
хтось може пояснити, як користуватися вище класом?
Бішан

4
Це рішення не є на 100% ідеальним для Android 4.2 (Cyanogenmod 10.1), використовуючи записи Android:. Висота завищеного TextView менша, ніж висота того, який ресурс надуває адаптер за замовчуванням. Отже, коли ви фактично вибираєте варіант, висота збільшується, ~ 10px в моєму Galaxy S, що не прийнятно. Я спробував декілька речей (гравітація, накладка, запас тощо), і жодна не працювала надійно на різних пристроях, тому я збираюся вибрати інше рішення.
Мараги

3
@DavidDoria Ви повинні використовувати клас NoDefaultSpinner у вашому файлі макета. Скопіюйте джерело зверху в проект, наприклад, в пакет com.example.customviews. Тепер у вашому макеті xml замість <Spinner ...> використовуйте <com.example.customviews.NoDefaultSpinner ...> Решта коду може залишатися однаковою. Не забудьте додати атрибут android: prompt до перегляду <com.example.customviews.NoDefaultSpinner> у своєму макеті.
Ridcully

2
@emmby spinnerBrand.setSelection (-1); не працює
Sachin C

291

Що ви можете зробити, це прикрасити ваш, SpinnerAdapterякий представляє перегляд "Вибрати параметр ...", щоб сповіщувач відображався спочатку без нічого вибраного.

Ось робочий приклад, перевірений для Android 2.3 та 4.0 (він не використовує нічого в бібліотеці сумісності, тому це повинно бути добре протягом деякого часу) Оскільки це декоратор, він повинен легко перевстановити існуючий код, і він також добре працює з CursorLoaders. (Поміняйте курсор на завершений cursorAdapterзвичайно ...)

Існує помилка Android, яка робить це трохи жорсткішим для повторного використання поглядів. (Отже, ви повинні використовувати setTagабо щось інше, щоб переконатися у convertViewправильності.) Spinner не підтримує кілька типів перегляду

Кодові примітки: 2 конструктори

Це дозволяє використовувати стандартний запит або визначити власне "нічого вибраного" як перший рядок, або обидва, або жодне. (Примітка. Деякі теми показують DropDown для Spinner замість діалогового вікна. В спадному меню зазвичай не відображається запит)

Ви визначаєте макет "виглядати" як підказки, наприклад, сірим кольором ...

Початково нічого не вибрано

Використовуючи стандартний запит (зауважте, що нічого не вибрано):

Зі стандартною підказкою

Або з підказкою і чимось динамічним (могло б не було і підказки):

Рядок і нічого вибраного рядка

Використання у наведеному вище прикладі

Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.planets_array, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setPrompt("Select your favorite Planet!");

spinner.setAdapter(
      new NothingSelectedSpinnerAdapter(
            adapter,
            R.layout.contact_spinner_row_nothing_selected,
            // R.layout.contact_spinner_nothing_selected_dropdown, // Optional
            this));

contact_spinner_row_nothing_selected.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textSize="18sp"
    android:textColor="#808080"
    android:text="[Select a Planet...]" />

NothingSelectedSpinnerAdapter.java

import android.content.Context;
import android.database.DataSetObserver;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;
import android.widget.SpinnerAdapter;

/**
 * Decorator Adapter to allow a Spinner to show a 'Nothing Selected...' initially
 * displayed instead of the first choice in the Adapter.
 */
public class NothingSelectedSpinnerAdapter implements SpinnerAdapter, ListAdapter {

    protected static final int EXTRA = 1;
    protected SpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    /**
     * Use this constructor to have NO 'Select One...' item, instead use
     * the standard prompt or nothing at all.
     * @param spinnerAdapter wrapped Adapter.
     * @param nothingSelectedLayout layout for nothing selected, perhaps
     * you want text grayed out like a prompt...
     * @param context
     */
    public NothingSelectedSpinnerAdapter(
      SpinnerAdapter spinnerAdapter,
      int nothingSelectedLayout, Context context) {

        this(spinnerAdapter, nothingSelectedLayout, -1, context);
    }

    /**
     * Use this constructor to Define your 'Select One...' layout as the first
     * row in the returned choices.
     * If you do this, you probably don't want a prompt on your spinner or it'll
     * have two 'Select' rows.
     * @param spinnerAdapter wrapped Adapter. Should probably return false for isEnabled(0)
     * @param nothingSelectedLayout layout for nothing selected, perhaps you want
     * text grayed out like a prompt...
     * @param nothingSelectedDropdownLayout layout for your 'Select an Item...' in
     * the dropdown.
     * @param context
     */
    public NothingSelectedSpinnerAdapter(SpinnerAdapter spinnerAdapter,
            int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context) {
        this.adapter = spinnerAdapter;
        this.context = context;
        this.nothingSelectedLayout = nothingSelectedLayout;
        this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        // This provides the View for the Selected Item in the Spinner, not
        // the dropdown (unless dropdownView is not set).
        if (position == 0) {
            return getNothingSelectedView(parent);
        }
        return adapter.getView(position - EXTRA, null, parent); // Could re-use
                                                 // the convertView if possible.
    }

    /**
     * View to show in Spinner with Nothing Selected
     * Override this to do something dynamic... e.g. "37 Options Found"
     * @param parent
     * @return
     */
    protected View getNothingSelectedView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedLayout, parent, false);
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
        // Spinner does not support multiple view types
        if (position == 0) {
            return nothingSelectedDropdownLayout == -1 ?
              new View(context) :
              getNothingSelectedDropdownView(parent);
        }

        // Could re-use the convertView if possible, use setTag...
        return adapter.getDropDownView(position - EXTRA, null, parent);
    }

    /**
     * Override this to do something dynamic... For example, "Pick your favorite
     * of these 37".
     * @param parent
     * @return
     */
    protected View getNothingSelectedDropdownView(ViewGroup parent) {
        return layoutInflater.inflate(nothingSelectedDropdownLayout, parent, false);
    }

    @Override
    public int getCount() {
        int count = adapter.getCount();
        return count == 0 ? 0 : count + EXTRA;
    }

    @Override
    public Object getItem(int position) {
        return position == 0 ? null : adapter.getItem(position - EXTRA);
    }

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public int getViewTypeCount() {
        return 1;
    }

    @Override
    public long getItemId(int position) {
        return position >= EXTRA ? adapter.getItemId(position - EXTRA) : position - EXTRA;
    }

    @Override
    public boolean hasStableIds() {
        return adapter.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return adapter.isEmpty();
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
        adapter.registerDataSetObserver(observer);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
        adapter.unregisterDataSetObserver(observer);
    }

    @Override
    public boolean areAllItemsEnabled() {
        return false;
    }

    @Override
    public boolean isEnabled(int position) {
        return position != 0; // Don't allow the 'nothing selected'
                                             // item to be picked.
    }

}

52
Це елегантне рішення проблеми. Код працює точно так само, як copy'n'-вставлений у мій проект. +1, не потрібно розмірковувати.
Річард Ле Месюр'є

2
Це чудове рішення. Якщо хтось хоче знати, як змінити заголовок не лише до вибору елемента, а весь час, під час виклику getView () просто повертайте getNothingSelectedView (або будь-який інший спеціальний перегляд) у всі часи. Спадний список все ще буде заповнений предметами з вашого адаптера, але тепер ви можете керувати заголовком ПІСЛЯ чогось вибраного.
OldSchool4664

6
Це дійсно елегантне рішення проблеми, яка не повинна існувати (спробуйте розробку Iphone). Чудово і дякую! Радий, що хтось пам’ятав шаблони тощо
user1700737

3
@prashantwosti, код оновлено для роботи з Lollipop. Зокрема getItemViewType () та getViewTypeCount ().
aaronvargas

3
@aaronvargas щойно вибрав предмет із спінера, чи можу я скасувати та вибрати "[Вибрати планету]"?
modabeckham

130

Я в кінцевому рахунку використовував Buttonнатомість. Хоча а Buttonне є Spinner, поведінку легко налаштувати.

Спочатку створіть адаптер як завжди:

String[] items = new String[] {"One", "Two", "Three"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
        android.R.layout.simple_spinner_dropdown_item, items);

Зауважте, що я використовую simple_spinner_dropdown_item як ідентифікатор макета. Це допоможе створити кращий вигляд під час створення діалогового вікна попередження.

У обробнику onClick для своєї кнопки я маю:

public void onClick(View w) {
  new AlertDialog.Builder(this)
  .setTitle("the prompt")
  .setAdapter(adapter, new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {

      // TODO: user specific action

      dialog.dismiss();
    }
  }).create().show();
}

І це все!


10
Я згоден з цією відповіддю. Крім того, кнопку, набагато простіше в стилі, ніж прядильник.
Romain Piel

@HRJ Я реалізував спосіб, запропонований u, але елемент, який було обрано раніше, не виділяється (означає, що перемикач повинен бути виділений зеленою крапкою посередині) .... Як я можу це досягти в методі OnClick () кнопка. Будь ласка, допоможіть мені HRJ .....
Avadhani Y

2
Кнопка з цим макетом ідеально <Кнопка android: id = "@ + id / city" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_margin = "5dp" android: gravity = "left" android: background = "@ android: dravable / btn_dropdown" android: text = "@ string / city_prompt" />
kml_ckr

Як би ви оновлювали текст кнопки, щоб відобразити вибір, як це станеться у спінері?
шим

3
вирішення проблеми: просто замість SetAdapter використовуйте SetSingleChoiceItems
Grzegorz Dev

67

По-перше, вам може бути цікавий promptатрибут Spinnerкласу. Дивіться на малюнку нижче, "Виберіть планету" - це підказка, яку можна встановити в XML за допомогою android:prompt="".

введіть тут опис зображення

Я збирався запропонувати підкласинг Spinner, де можна було б підтримувати два адаптери внутрішньо. Один адаптер, який має опцію "Вибрати один", а інший справжній адаптер (із фактичними параметрами), потім використовуючи кнопку OnClickListenerдля перемикання адаптерів до появи діалогового вікна вибору. Однак, спробувавши реалізувати цю ідею, я прийшов до висновку, що ви не можете отримувати OnClickподії для самого віджета.

Ви можете обернути спінер в інший вигляд, перехопити клацання на зображенні, а потім сказати своєму CustomSpinnerпереключити адаптер, але це здається жахливим злом.

Вам справді потрібно показати "Вибрати один"?


36
Справа не лише в тому, що потрібно показувати "Вибрати один", але також вирішує випадок, коли значення спінера може бути залишено порожнім.
greg7gkb

5
Крім того, за допомогою цього параметра Земля відображається як вибір на Spinner, перш ніж щось було обрано, для мого додатка я вважаю, що користувач міг би сказати, що ще нічого не вибрав
dylan murphy

2
це насправді не відповідає на питання. люди шукають спосіб отримати сам спінер за замовчуванням шоу "Вибрати один", а не перший пункт у списку планет, у цьому прикладі
JMRboosties

58

Цей код перевірений і працює на Android 4.4

введіть тут опис зображення

Spinner spinner = (Spinner) activity.findViewById(R.id.spinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_spinner_dropdown_item) {

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {

                View v = super.getView(position, convertView, parent);
                if (position == getCount()) {
                    ((TextView)v.findViewById(android.R.id.text1)).setText("");
                    ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); //"Hint to be displayed"
                }

                return v;
            }       

            @Override
            public int getCount() {
                return super.getCount()-1; // you dont display last item. It is used as hint.
            }

        };

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        adapter.add("Daily");
        adapter.add("Two Days");
        adapter.add("Weekly");
        adapter.add("Monthly");
        adapter.add("Three Months");
        adapter.add("HINT_TEXT_HERE"); //This is the text that will be displayed as hint.


        spinner.setAdapter(adapter);
        spinner.setSelection(adapter.getCount()); //set the hint the default selection so it appears on launch.
        spinner.setOnItemSelectedListener(this);

getItem(getCount())для мене підкреслено червоним? Неможливо вирішити метод setHint
Zapnologica

У мене є сумніви, я побачив багато рішень у цій темі. Але чому всі додають підказку до останнього. Неправильно додавати підказку в перший рядок?
akashPatra

Я не можу встановити 'setOnItemSelectedListener (це);' тому що я використовую 'реалізує NavigationView.OnNavigationItemSelectedListener', чи можу я видалити 'setOnItemSelectedListener (це);' без жодних питань?
CGR

@akashpatra Причина, чому вони додають підказку останньому, полягає в тому, що ArrayAdapter для спінера може отримувати свої значення з різних джерел під час виконання.
VinKrish

це мені справді допомогло
суніль

31

Я знайшов таке рішення:

String[] items = new String[] {"Select One", "Two", "Three"};
Spinner spinner = (Spinner) findViewById(R.id.mySpinner);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);

spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
        items[0] = "One";
        selectedItem = items[position];
    }

    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});

Просто змініть масив [0] на "Вибрати один", а потім у onItemSelected перейменуйте його на "Один".

Не класне рішення, але воно працює: D


5
Це для мене не вийшло. Після вибору елемента "Один" він все ще пише "Вибрати один".
Лео Ландау

Ця звичайна робота викликає інтерфейс onItemSelected, який буде вперше викликати завжди.
Вайбхав Кадам

20

Не існує API за замовчуванням, щоб встановити натяк на Spinner. Щоб додати його, нам знадобиться невелике вирішення, що не є реалізацією безпеки

List<Object> objects = new ArrayList<Object>();
objects.add(firstItem);
objects.add(secondItem);
// add hint as last item
objects.add(hint);

HintAdapter adapter = new HintAdapter(context, objects, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

Spinner spinnerFilmType = (Spinner) findViewById(R.id.spinner);
spinner.setAdapter(adapter);

// show hint
spinner.setSelection(adapter.getCount());

Джерело адаптера:

public class HintAdapter
        extends ArrayAdapter<Objects> {

    public HintAdapter(Context theContext, List<Object> objects) {
        super(theContext, android.R.id.text1, android.R.id.text1, objects);
    }

    public HintAdapter(Context theContext, List<Object> objects, int theLayoutResId) {
        super(theContext, theLayoutResId, android.R.id.text1, objects);
    }

    @Override
    public int getCount() {
        // don't display last item. It is used as hint.
        int count = super.getCount();
        return count > 0 ? count - 1 : count;
    }
}

Першоджерело


що таке R.id.text1? це якась компонування чи перегляд? уточнюйте, будь ласка, свою відповідь
Ананд Савяні

Має бутиandroid.R.id.text1
Яків Моспан

У мене є сумніви, я побачив багато рішень у цій темі. Але чому всі додають підказку до останнього. Неправильно додавати підказку в перший рядок?
akashPatra

@akashpatra я точно не пам'ятаю, але, здається, виникла якась проблема, коли я намагався скласти це як список перших позицій. У будь-якому випадку ви завжди можете спробувати це і прокоментувати тут, вся магія тут навколо getCountметоду
Yakiv Mospan

@YakivMospan Я отримую NPE, коли використовую це, ймовірно, через Reflection при використанні ProGuard. Чи знаєте ви, як це виправити?
Алан

17

Тут є багато відповідей, але я здивований, що ніхто не запропонував просте рішення: Помістіть TextView поверх Spinner. Встановіть слухач кліків на TextView, який приховує TextView, показує Spinner і викликає spinner.performClick ().


9

У мене виникла така ж проблема зі спінером, з порожнім виділенням, і я знайшов краще рішення. Погляньте на цей простий код.

Spinner lCreditOrDebit = (Spinner)lCardPayView.findViewById(R.id.CARD_TYPE);
spinneradapter lAdapter = 
  new spinneradapter(
    BillPayScreen.this, 
    ndroid.R.layout.simple_spinner_item,getResources().getStringArray(R.array.creditordebit));
lAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
lCreditOrDebit.setAdapter(lAdapter);

Тут spinneradapter - це невелике налаштування для arrayadapter. Це виглядає приблизно так:

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;

public class spinneradapter extends ArrayAdapter<String>{
    private Context m_cContext;
    public spinneradapter(Context context,int textViewResourceId, String[] objects) {
        super(context, textViewResourceId, objects);
        this.m_cContext = context;
    }

    boolean firsttime = true;
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(firsttime){
            firsttime = false;
            //Just return some empty view
            return new ImageView(m_cContext);
        }
        //Let the array adapter take care of it this time.
        return super.getView(position, convertView, parent);
    }
}

6
Проблема такого підходу полягає в тому, що він все одно вибирає перший пункт у списку, коли список з'являється. Оскільки це вже вибрано, ви не можете торкнутися його, щоб вибрати - він діє так, як ніби вибраного не відбулося.
jwadsack


6

XML-файл:

<Spinner android:id="@+id/locationSpinner"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:prompt="@string/select_location" />

Діяльність:

private Spinner featuresSelection;
private ArrayAdapter<CharSequence> featuresAdapter;
private List<CharSequence> featuresList;

onCreate:

featuresList = new ArrayList<CharSequence>();
featuresAdapter = new ArrayAdapter<CharSequence>(this,
  android.R.layout.simple_spinner_item, featuresList);
featuresAdapter.setDropDownViewResource(
  android.R.layout.simple_spinner_dropdown_item);
featuresSelection = ((Spinner) yourActivity.this
  .findViewById(R.id.locationSpinner));
featuresSelection.setAdapter(featuresAdapter);
featuresSelection.setOnItemSelectedListener(
  new MyOnItemSelectedListener());

Деякі функції (додайте речі до адаптера програмно)>

featuresAdapter.add("some string");

Тепер у вас порожній спінер і ви можете написати код, щоб не відкривати діалогове вікно, якщо воно порожнє. Або вони можуть натиснути назад. Але ви також заповнюєте його функцією або іншим списком під час виконання.


Також не потрібно сповіщатиDataSetChanged (), оскільки за замовчуванням слід встановити значення true.
trgraglia

4

Я спробував, як наступне. Візьміть кнопку і надайте їй подію натискання. Змінивши фон кнопки, здається, що це прядок.

Заявити як глобальні змінні alardialog та значення за замовчуванням ..

AlertDialog d;
static int default_value = 0;
final Button btn = (Button) findViewById(R.id.button1);
btn .setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v)
{
    //c.show();
    final CharSequence str[] = {"Android","Black Berry","Iphone"};
        AlertDialog.Builder builder =
          new AlertDialog.Builder(TestGalleryActivity.this).setSingleChoiceItems(
            str, default_value,new  DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int position)
            {
                Toast.makeText(TestGalleryActivity.this,
                               "" + position,
                               Toast.LENGTH_SHORT).show();
                default_value = position;
                btn.setText(str[position]);
                if(d.isShowing())
                    d.dismiss();
            }
        }).setTitle("Select Any");
        d = builder.create();
        d.show();
    }
});

4

Це мій шлях:

List<String> list = new ArrayList<String>();
list.add("string1");
list.add("string2");
list.add("string3");
list.add("[Select one]");
final int listsize = list.size() - 1;
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item, list) {
 @Override
public int getCount() {
    return(listsize); // Truncate the list
}
};
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(dataAdapter);

mySpinner.setSelection(listsize); // Hidden item to appear in the spinner

це відкриває
спінер

3

Погляньте на додаток iosched для загального рішення щодо додавання елемента вгору списку. Зокрема, якщо ви використовуєте CursorAdapter, подивіться на TracksAdapter.java, який розширює це визначення, щоб забезпечити метод "setHasAllItem" та пов'язаний з ним код для управління кількістю списку для обробки зайвого елемента вгорі.

Використовуючи спеціальний адаптер, ви можете встановити текст на "Вибрати один" або будь-що інше, про що ви хочете сказати цей головний елемент.


3

У мене на моєму main.xml є спінер і його ідентифікатор є @+id/spinner1

це те, що я пишу у своїй функції OnCreate:

spinner1 = (Spinner)this.findViewById(R.id.spinner1);
final String[] groupes = new String[] {"A", "B", "C", "D", "E", "F", "G", "H"};
ArrayAdapter<CharSequence> featuresAdapter = new ArrayAdapter<CharSequence>(this, android.R.layout.simple_spinner_item, new ArrayList<CharSequence>());
featuresAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner1.setAdapter(featuresAdapter);
for (String s : groupes) featuresAdapter.add(s);

spinner1.setOnItemSelectedListener(new OnItemSelectedListener() {
     public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id) {
         // Here go your instructions when the user chose something
         Toast.makeText(getBaseContext(), groupes[position], 0).show();
     }
     public void onNothingSelected(AdapterView<?> arg0) { }
});

Він не потребує будь-якої реалізації в класі.


3

Я знайшов для цього багато хороших рішень. Більшість працює, додаючи елемент до кінця адаптера, і не відображайте останній елемент у спадному списку. Великою проблемою для мене було те, що випадаючий список спінерів розпочнеться знизу списку. Тому користувач бачить останні предмети замість перших (якщо у них багато предметів для показу), після цього вперше торкніться спінера.

Тому я ставлю пункт підказки на початок списку. і приховати перший елемент у спадному списку.

private void loadSpinner(){

    HintArrayAdapter hintAdapter = new HintArrayAdapter<String>(context, 0);

    hintAdapter.add("Hint to be displayed");
    hintAdapter.add("Item 1");
    hintAdapter.add("Item 2");
            .
            .
    hintAdapter.add("Item 30");

    spinner1.setAdapter(hintAdapter);

    //spinner1.setSelection(0); //display hint. Actually you can ignore it, because the default is already 0
    //spinner1.setSelection(0, false); //use this if don't want to onItemClick called for the hint

    spinner1.setOnItemSelectedListener(yourListener);
}

private class HintArrayAdapter<T> extends ArrayAdapter<T> {

    Context mContext;

    public HintArrayAdapter(Context context, int resource) {
        super(context, resource);
        this.mContext = context
    }

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(android.R.layout.simple_spinner_item, parent, false);
        TextView texview = (TextView) view.findViewById(android.R.id.text1);

        if(position == 0) {
            texview.setText("");
            texview.setHint(getItem(position).toString()); //"Hint to be displayed"
        } else {
            texview.setText(getItem(position).toString());
        }

        return view;
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {

        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
        View view;

        if(position == 0){
            view = inflater.inflate(R.layout.spinner_hint_list_item_layout, parent, false); // Hide first row
        } else {
            view = inflater.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
            TextView texview = (TextView) view.findViewById(android.R.id.text1);
            texview.setText(getItem(position).toString());
        } 

        return view;
    }
}

встановіть макет нижче @Override getDropDownView (), коли позиція 0, щоб приховати перший рядок підказки.

R.layout.spinner_hint_list_item_layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

</LinearLayout>

3

Крім того, є простий трюк, щоб показати за замовчуванням:

Ви можете додати до списку значення за замовчуванням, а потім додати всю свою колекцію за допомогою list.addAll(yourCollection);

Зразок діючого коду тут:

List<FuelName> fuelList = new ArrayList<FuelName>();
                    fuelList.add(new FuelName(0,"Select One"));
                    fuelList.addAll(response.body());
                    ArrayAdapter adapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item, fuelList);
                    //fuelName.setPrompt("Select Fuel");
                    fuelName.setAdapter(adapter);

Сподіваюся, що це відновить ваші складності. Щасливого кодування!


2

Я думаю, що найпростішим способом є створення фіктивного елемента в індексі 0 із зазначенням "вибрати один", а потім із збереженням, можливо, перевірте, що вибір не 0.


4
Що з переглядом списку елементів? Ви хочете побачити позицію "вибрати один" вгорі? Справа не лише в економії.
Кшиштоф Волній

@KrzysztofWolny Spinner за замовчуванням відображає елемент в позиції 0
Rds

2

Отже, це мій останній приклад "все-в" для віджимання кнопок

У Activity_my_form.xml

    <Button
        android:id="@+id/btnSpinnerPlanets"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="left|center_vertical"
        android:singleLine="true"
        android:text="@string/selectAPlanet"
        android:textSize="10sp"
        android:background="@android:drawable/btn_dropdown">
    </Button>

В рядках.xml

<string name="selectAPlanet">Select planet&#8230;</string>

<string-array name="planets__entries">
    <item>The Sun with a name very long so long long long long longThe Sun with a name very long so long long long long longThe Sun with a name very long so long long long long long</item>
    <item>Mercury</item>
    <item>Venus</item>
    <item>Earth</item>
    <item>Mars</item>
    <item>Jupiter</item>
    <item>Saturn</item>
    <item>Uranus</item>
    <item>Neptune</item>
</string-array>

У MyFormActivity.java

public class MyFormActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ((Button) findViewById(R.id.btnSpinnerPlanets)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final String[] items = view.getResources().getStringArray(R.array.planets__entries);
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(MyFormActivity.this, android.R.layout.simple_spinner_dropdown_item, items);
                new AlertDialog.Builder(MyFormActivity.this).setTitle("the prompt").setAdapter(adapter, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ((Button) findViewById(R.id.btnSpinnerPlanets)).setText(items[which]);
                        dialog.dismiss();
                    }
                }).create().show();
            }
        });     

    }

}   

Нарешті, я отримав розмір шрифту, який не можна налаштувати, жодна кнопка, що вибирається, кнопка, що вибирається !!! Завдяки HRJ


1

Під час розширення SpinnerAdapterви переосмислюєте два Viewспособи виготовлення getView(int, View, ViewGroup)та getDropDownView(int, View, ViewGroup). Перший постачає Viewвставлене в Spinnerсебе; другий постачає Viewв спадному списку (як випливає з назви). Ви можете змінити getView(...)так, щоб, поки елемент не був обраний, він відображав, що TextViewмістить підказку; потім, коли ви виявите, що елемент був обраний, ви змінюєте його, щоб відобразити TextViewвідповідне.

public class PromptingAdapter extends SpinnerAdapter {

    //... various code ...

    private boolean selectionmade = false;

    //call this method from the OnItemSelectedListener for your Spinner
    public setSelectionState(boolean b) {
        selectionmade = b;
    }

    @Override
    public View getView(int position, View recycle, ViewGroup container) {
        if(selectionmade) {
            //your existing code to supply a View for the Spinner
            //you could even put "return getDropDownView(position, recycle, container);"
        }
        else {
            View output;
            if(recycle instanceof TextView) {
                 output = recycle;
            }
            else {
                 output = new TextView();
                 //and layout stuff
            }
            output.setText(R.string.please_select_one);
            //put a string "please_select_one" in res/values/strings.xml
            return output;
        }
    }

//...
}

1
Я виявив недолік у цьому методі: Spinner автоматично вибирає елемент негайно. Невдовзі я знайду шлях.
Ендрю Вілд

Я говорив занадто рано. Однак я не здався. Зауважте, що згідно з Spinnerпідручником (який нібито відображається ToastПІСЛЯ ви вибрали предмет) цей ОПОВНІТ працює: developer.android.com/resources/tutorials/views/…
Ендрю Вілд

1

Для тих, хто використовує Xamarin, ось C # еквівалент відповіді ааронваргасу вище.

using Android.Content;
using Android.Database;
using Android.Views;
using Android.Widget;
using Java.Lang;

namespace MyNamespace.Droid
{ 
  public class NothingSelectedSpinnerAdapter : BaseAdapter, ISpinnerAdapter, IListAdapter
  {
    protected static readonly int EXTRA = 1;
    protected ISpinnerAdapter adapter;
    protected Context context;
    protected int nothingSelectedLayout;
    protected int nothingSelectedDropdownLayout;
    protected LayoutInflater layoutInflater;

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, Context context) : this(spinnerAdapter, nothingSelectedLayout, -1, context)
    {
    }

    public NothingSelectedSpinnerAdapter(ISpinnerAdapter spinnerAdapter, int nothingSelectedLayout, int nothingSelectedDropdownLayout, Context context)
    {
      this.adapter = spinnerAdapter;
      this.context = context;
      this.nothingSelectedLayout = nothingSelectedLayout;
      this.nothingSelectedDropdownLayout = nothingSelectedDropdownLayout;
      layoutInflater = LayoutInflater.From(context);
    }

    protected View GetNothingSelectedView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedLayout, parent, false);
    }

    protected View GetNothingSelectedDropdownView(ViewGroup parent)
    {
      return layoutInflater.Inflate(nothingSelectedDropdownLayout, parent, false);
    }

    public override Object GetItem(int position)
    {
      return position == 0 ? null : adapter.GetItem(position - EXTRA);
    }

    public override long GetItemId(int position)
    {
      return position >= EXTRA ? adapter.GetItemId(position - EXTRA) : position - EXTRA;
    }

    public override View GetView(int position, View convertView, ViewGroup parent)
    {
      // This provides the View for the Selected Item in the Spinner, not
      // the dropdown (unless dropdownView is not set).
      if (position == 0)
      {
        return GetNothingSelectedView(parent);
      }

      // Could re-use the convertView if possible.
      return this.adapter.GetView(position - EXTRA, null, parent);
    }

    public override int Count
    {
      get
      {
        int count = this.adapter.Count;
        return count == 0 ? 0 : count + EXTRA;
      }
    }

    public override View GetDropDownView(int position, View convertView, ViewGroup parent)
    {
      // Android BUG! http://code.google.com/p/android/issues/detail?id=17128 -
      // Spinner does not support multiple view types
      if (position == 0)
      {
        return nothingSelectedDropdownLayout == -1 ?
          new View(context) :
          GetNothingSelectedDropdownView(parent);
      }

      // Could re-use the convertView if possible, use setTag...
      return adapter.GetDropDownView(position - EXTRA, null, parent);
    }

    public override int GetItemViewType(int position)
    {
      return 0;
    }

    public override int ViewTypeCount => 1;

    public override bool HasStableIds => this.adapter.HasStableIds;

    public override bool IsEmpty => this.adapter.IsEmpty;

    public override void RegisterDataSetObserver(DataSetObserver observer)
    {
      adapter.RegisterDataSetObserver(observer);
    }

    public override void UnregisterDataSetObserver(DataSetObserver observer)
    {
      adapter.UnregisterDataSetObserver(observer);
    }

    public override bool AreAllItemsEnabled()
    {
      return false;
    }

    public override bool IsEnabled(int position)
    {
      return position > 0;
    }
  }
}

1

Я також вирішив цю проблему, використовуючи наступний код. Припустимо, у вас є список елементів, наприклад

ArrayList<Item> itemsArrayList = new ArrayList<Item>();
Item item1 = new Item();
item1.setId(1);
item1.setData("First Element");
Item item2 = new Item();
item2.setId(2);
Item2.setData("Second Element");
itemsArrayList.add(item1);
itemsArrayList.add(item2);

Тепер ми повинні надати рядки спінеру, оскільки спінер не може зрозуміти об'єкт. Таким чином, ми створимо новий список масивів із рядковими елементами на кшталт цього ->

ArrayList<String> itemStringArrayList = new ArrayList<String>();
for(Item item : itemsArrayList) {
    itemStringArrayList.add(item.getData());
}

Тепер у нас є itemStringArrayListсписок масивів з двома рядковими елементами. І ми повинні показати текст "Вибрати елемент" як перший елемент. Тому нам потрібно вставити новий рядок у itemStringArrayList.

itemStringArrayList.add("Select Item");

Тепер у нас є список масивів itemsArrayListі ми хочемо показати два елементи у спадному меню. Але умова тут полягає в тому, що якщо ми нічого не вибрали, то він Select Itemповинен з’явитися як перший елемент, який не буде ввімкнено.

Тож ми можемо реалізувати подібну функціональність. Якщо вам потрібно завантажити елементи списку масивів у спінер Android. Тож вам доведеться використовувати якийсь адаптер. Тому тут я буду використовувати ArrayAdapter. Ми також можемо використовувати адаптер для налаштування.

ArrayAdapter<String> itemsArrayAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.spinner_item, itemsArrayList){
        @Override
        public boolean isEnabled(int position) {
            if(position == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        @Override
        public View getDropDownView(int position, View convertView,
                                    ViewGroup parent) {
            View view = super.getDropDownView(position, convertView, parent);
            TextView tv = (TextView) view;
            if(position == 0){
                // Set the hint text color gray
                tv.setTextColor(Color.GRAY);
            }
            else {
                tv.setTextColor(Color.BLACK);
            }
            return view;
        }
    };

itemsArrayAdapter.setDropDownViewResource(R.layout.spinner_item);
your_spinner_name.setAdapter(itemsArrayAdapter);

Ось у цьому коді. ми використовуємо індивідуальний лічильник макета , тобто R.layout.spinner_item. Це простий перегляд тексту

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"
    android:textStyle="italic"
    android:fontFamily="sans-serif-medium"
    />

Нам потрібно відключити перший текст у спінері. Тож для позиції 0 ми відключаємо текст. І колір також ми можемо встановити, перекривши метод getDropDownView. Таким чином, ми отримаємо очікуваний спінер.


0

Я б просто скористався RadioGroup з RadioButtons, якщо у вас є лише три варіанти, ви можете зробити їх спочатку невірно.


0

Жодна з поданих раніше відповідей насправді не працювала так, як я хотів вирішити це питання. Для мене ідеальним рішенням було б «Вибрати один» (або будь-який початковий текст) під час першого відображення спінера. Коли користувач натискає на спінер, початковий текст не повинен бути частиною випадаючого меню, що відображається.

Щоб ще більше ускладнити мою конкретну ситуацію, мої дані спінера надходять з курсору, який завантажується через зворотні виклики LoaderManager.

Після значних експериментів я придумав таке рішення:

public class MyFragment extends Fragment implements
LoaderManager.LoaderCallbacks<Cursor>{

private static final String SPINNER_INIT_VALUE = "Select A Widget";
private Spinner mSpinner;
private int mSpinnerPosition;
private boolean mSpinnerDropDownShowing = false;
private View mSpinnerDropDown;

private MyCursorAdapter mCursorAdapter;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
...

mCursorAdapter = new MyCursorAdapter(getActivity());

mSpinner = (Spinner) rootView.findViewById(R.id.theSpinner);
mSpinner.setOnTouchListener(mSpinnerTouchListener);
mSpinner.setAdapter(mCursorAdapter);

...
}

//Capture the touch events to toggle the spinner's dropdown visibility
private OnTouchListener mSpinnerTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(mSpinnerDropDown != null && mSpinnerDropDownShowing == false){
            mSpinnerDropDownShowing = true;
            mSpinnerDropDown.setVisibility(View.VISIBLE);
        }
        return false;
    }
};

//Capture the click event on the spinner drop down items
protected OnClickListener spinnerItemClick = new OnClickListener(){

    @Override
    public void onClick(View view) {
        String widget = ((TextView) view.findViewById(android.R.id.text1)).getText().toString();

        if(!widget.equals(SPINNER_INIT_VALUE)){
            if(mCursorAdapter != null){
                Cursor cursor = mCursorAdapter.getCursor();
                if(cursor.moveToFirst()){
                    while(!cursor.isAfterLast()){
                        if(widget.equals(cursor.getString(WidgetQuery.WIDGET_NAME))){

                            ...

                            //Set the spinner to the correct item
                            mSpinnerPosition = cursor.getPosition() + 1;
                            mSpinner.setSelection(mSpinnerPosition);
                            break;
                        }
                        cursor.moveToNext();
                    }
                }
            }
        }

        //Hide the drop down. Not the most elegent solution but it is the only way I could hide/dismiss the drop down
        mSpinnerDropDown = view.getRootView();
        mSpinnerDropDownShowing = false;
        mSpinnerDropDown.setVisibility(View.GONE);
    }
};

private class MyCursorAdapter extends CursorAdapter {

    private final int DISPLACEMENT = 1;
    private final int DEFAULT_ITEM_ID = Integer.MAX_VALUE;

    private Activity mActivity;

    public MyCursorAdapter(Activity activity) {
            super(activity, null, false);
            mActivity = activity;
    }

    //When loading the regular views, inject the defualt item
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(position == 0){
            if(convertView == null){
                convertView = mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
            }
            return getDefaultItem(convertView);
        }
        return super.getView(position - DISPLACEMENT, convertView, parent);
    }

    //When loading the drop down views, set the onClickListener for each view
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent){
        View view = super.getDropDownView(position, convertView, parent);
        view.setOnClickListener(spinnerItemClick);
        return view;
    }

    //The special default item that is being injected
    private View getDefaultItem(View convertView){
        TextView text = (TextView) convertView.findViewById(android.R.id.text1);
        text.setText(SPINNER_INIT_VALUE);
        return convertView;
    }

    @Override
    public long getItemId(int position) {
        if (position == 0) {
            return DEFAULT_ITEM_ID;
        }
        return super.getItemId(position - DISPLACEMENT);
    }

    @Override
    public boolean isEnabled(int position) {
        return position == 0 ? true : super.isEnabled(position - DISPLACEMENT);
    }

    @Override
    public int getViewTypeCount() {
        return super.getViewTypeCount() + DISPLACEMENT;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return super.getViewTypeCount();
        }

        return super.getItemViewType(position - DISPLACEMENT);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return mActivity.getLayoutInflater().inflate(R.layout.list_item_widget, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor){

        if(cursor.isAfterLast()){
            return;
        }

        TextView text = (TextView) view.findViewById(android.R.id.text1);
        String WidgetName = cursor.getString(WidgetQuery.WIDGET_NAME);
        text.setText(WidgetName);
    }
}
}

0

Я впораюся з цим за допомогою кнопки замість віджиму. У мене на GitHub розроблений зразок проекту.

У проекті я показую і Spinner, і кнопку, щоб показати, що вони дійсно виглядають однаково. Крім кнопки, ви можете встановити початковий текст на все, що завгодно.

Ось як виглядає діяльність:

package com.stevebergamini.spinnerbutton;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Spinner;

public class MainActivity extends Activity {

    Spinner spinner1;
    Button button1;
    AlertDialog ad;
    String[] countries;

    int selected = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        spinner1 = (Spinner) findViewById(R.id.spinner1);
        button1 = (Button) findViewById(R.id.button1);

        countries = getResources().getStringArray(R.array.country_names);

        //  You can also use an adapter for the allert dialog if you'd like
        //  ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, countries);        

        ad = new AlertDialog.Builder(MainActivity.this).setSingleChoiceItems(countries, selected,  
                new  DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            button1.setText(countries[which]);
                            selected = which;
                            ad.dismiss();

                        }}).setTitle(R.string.select_country).create(); 


        button1.setOnClickListener( new OnClickListener(){

            @Override
            public void onClick(View v) {
                ad.getListView().setSelection(selected);
                ad.show();              
            }});

    }

}

ПРИМІТКА: Так, я розумію, що це залежить від застосованої Теми, і вигляд буде дещо іншим, якщо використовувати Theme.Holo. Однак якщо ви використовуєте одну із застарілих тем, як-от Theme.Black, вам добре.


0

якщо ви стикаєтеся з цією проблемою, коли ваші елементи заповнюються з курсору баз даних ,

найпростіше рішення, яке я знайшов у цій відповіді ТА:

використовуйте UNION у запиті адаптера курсору та додайте додатковий елемент із id = -1 до результату запиту, не додаючи його до БД:

щось на зразок:

db.rawQuery ("SELECT iWorkerId as _id, nvLastName як ім'я від Worker w UNION SELECT -1 як _id, '' як ім'я", null);

якщо вибраний елемент дорівнює -1, то це значення за замовчуванням. Інакше це запис із таблиці.


0

Здається, банальне рішення, але я зазвичай проставляю TextView в передній частині спінера. Весь Xml виглядає приблизно так. (Ей, хлопці, не стріляйте в мене, я знаю, що деяким з вас такий шлюб не подобається):

<FrameLayout
    android:id="@+id/selectTypesLinear"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <Spinner
        android:id="@+id/spinnerExercises"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:entries="@array/exercise_spinner_entries"
        android:prompt="@string/exercise_spinner_prompt"
     />                         
    <TextView
        android:id="@+id/spinnerSelectText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hey! Select this guy!"
        android:gravity="center"
        android:background="#FF000000" />


</FrameLayout>

Потім я приховую TextView, коли вибрано Елемент. Очевидно, колір тла TextView повинен бути таким же, як і Spinner. Працює на Android 4.0. Не знаю про старіші версії.

Так. Оскільки Spinner викликає setOnItemSelectedListener на початку, приховування перегляду тексту може бути трохи складним, але це можна зробити так:

    Boolean controlTouched;

    exerciseSpinner.setOnTouchListener(new OnTouchListener() {


        @Override
        public boolean onTouch(View v, MotionEvent event) {
            controlTouched = true; // I touched it but but not yet selected an Item.
            return false;
        }

    });
    exerciseSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1,
                int arg2, long arg3) {
            if (controlTouched) { // Are you sure that I touched it with my fingers and not someone else  ?
                spinnerSelText.setVisibility(View.GONE);
            }
        }

        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
        }

    });

0

для мене це працювало щось подібне. має покращення, яке змінює лише текст у деяких параметрах, а не у всіх.

Спочатку я беру імена спіннера і створюю масив адаптера з налаштованим представленням, але це вже не має значення, ключ переосмислює getView, а всередині змінюють значення, які потрібно змінити. У моєму випадку був лише перший, решту я залишаю оригінал

public void rellenarSpinnerCompeticiones(){
        spinnerArrayCompeticiones = new ArrayList<String>();
        for(Competicion c: ((Controlador)getApplication()).getCompeticiones()){
            spinnerArrayCompeticiones.add(c.getNombre());
        }
        //ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,R.layout.spinner_item_competicion,spinnerArrayCompeticiones);
        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, R.layout.spinner_item_competicion, spinnerArrayCompeticiones){
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                final View v = vi.inflate(R.layout.spinner_item_competicion, null);
                final TextView t = (TextView)v.findViewById(R.id.tvCompeticion);
                if(spinnerCompeticion.getSelectedItemPosition()>0){
                    t.setText(spinnerArrayCompeticiones.get(spinnerCompeticion.getSelectedItemPosition()));
                }else{
                    t.setText("Competiciones");
                }
                return v;
            }
        };
        spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerCompeticion.setAdapter(spinnerArrayAdapter);
    }

0

ось простий

    private boolean isFirst = true;
private void setAdapter() {
    final ArrayList<String> spinnerArray = new ArrayList<String>();     
    spinnerArray.add("Select your option");
    spinnerArray.add("Option 1");
    spinnerArray.add("Option 2");
    spin.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
            TextView tv = (TextView)selectedItemView;
            String res = tv.getText().toString().trim();
            if (res.equals("Option 1")) {
            //do Something
        } else if (res.equals("Option 2")) {
            //do Something else
        }
        }

        @Override
        public void onNothingSelected(AdapterView<?> parentView) { }

    });

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.my_spinner_style,spinnerArray) {
         public View getView(int position, View convertView, ViewGroup parent) {
             View v = super.getView(position, convertView, parent);
             int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 25, getResources().getDisplayMetrics());                  
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).getLayoutParams().height = height;
             ((TextView) v).setGravity(Gravity.CENTER);
             ((TextView) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, 19);
             ((TextView) v).setTextColor(Color.WHITE);
             return v;
         }

         public View getDropDownView(int position, View convertView,
                 ViewGroup parent) {
             if (isFirst) {
                 isFirst = false;
                 spinnerArray.remove(0);
             }
             View v = super.getDropDownView(position, convertView, parent);                  
             ((TextView) v).setTextColor(Color.argb(255, 70, 70, 70));
             ((TextView) v).setTypeface(tf2);
             ((TextView) v).setGravity(Gravity.CENTER);
             return v;
         }
     };
     spin.setAdapter(adapter);
}

0

Зверніться до однієї з вищезазначених відповідей: https://stackoverflow.com/a/23005376/1312796

Я додав свій код, щоб виправити невелику помилку. Що там, де не знайдено даних .. Як показати текст підказки ..!

Ось мій трюк ... Зі мною добре працює. !

Спробуйте помістити ваш спінер у відносну_ладу та вирівняйте Textview зі своїм спінером та грайте із видимістю Textview (SHOW / HIDE), коли адаптер спінера завантажується чи порожній.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="20dp"
android:background="#ededed"
android:orientation="vertical">



    <TextView
        android:id="@+id/txt_prompt_from"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:textColor="@color/gray"
        android:textSize="16sp"
        android:layout_alignStart="@+id/sp_from"
        android:text="From"
        android:visibility="gone"/>

    <Spinner
        android:id="@+id/sp_from"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        />

Ось код:

  txt__from = (TextView) rootView.findViewById(R.id.txt_prompt_from);

виклик цього методу після та перед тим, як адаптер спінера завантажений та порожній.

setPromptTextViewVisibility (); //True or fales 

public void setPromptTextViewVisibility (boolean visible )
{
    if (visible)
    {
        txt_from.setVisibility(View.VISIBLE);
    }
    else
    {
        txt_from.setVisibility(View.INVISIBLE);
    }

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.