Как сделать Android Spinner с начальным текстом «Select One»?

569

Я хочу использовать Spinner, который изначально (когда пользователь еще не сделал выбор) отображает текст «Select One». Когда пользователь щелкает счетчик, отображается список элементов, и пользователь выбирает один из вариантов. После того, как пользователь сделал выбор, выбранный элемент отображается в Spinner вместо «Select One».

У меня есть следующий код для создания 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
многоразовый счетчик: github.com/henrychuangtw/ReuseSpinner
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);
        }
    }
}
emmby
источник
7
@emmby У вас есть идея, как очистить выбор после того, как пользователь установил его? Я попытался изменить рефакторинг двух вызовов invoke () в метод clearSelection (), но на самом деле это не работает. Хотя всплывающий список показывает ранее выбранный элемент как невыбранный, виджет счетчика покажет его как выбранный, и если пользователь снова выбирает тот же элемент, onItemSelected () не вызывается.
Qwertie
3
Могут ли некоторые объяснить, как использовать выше класс?
Бишан
4
Это решение не идеально на 100% на Android 4.2 (Cyanogenmod 10.1), используя Android: записи. Высота надутого TextView меньше, чем высота того ресурса, который раздувает адаптер по умолчанию. Таким образом, когда вы на самом деле выбираете опцию, высота увеличивается, ~ 10 пикселей в моей Galaxy S, что недопустимо. Я пробовал несколько вещей (гравитация, отступы, поля и т. Д.), И ни одна из них не работала надежно на разных устройствах, поэтому я выберу другое решение.
Мараг
3
@DavidDoria Вы должны использовать класс NoDefaultSpinner в вашем файле макета. Скопируйте исходный код в ваш проект, например, в пакет com.example.customviews. Теперь в вашем макете XML вместо <Spinner ...> используйте <com.example.customviews.NoDefaultSpinner ...> Остальная часть кода может остаться прежней. Не забудьте добавить атрибут android: prompt в представление <com.example.customviews.NoDefaultSpinner> в макете.
Чудакулли
2
@emmby spinnerBrand.setSelection (-1); не работает
Sachin C
291

Что вы можете сделать, это украсить свой SpinnerAdapter вариант изображением «Выбор варианта ...», чтобы Spinner отображался без выбора.

Вот рабочий пример, протестированный для 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.
    }

}
aaronvargas
источник
52
Это элегантное решение проблемы. Код работает точно так же, как copy'n'pasted в моем проекте. +1 для отражения не требуется.
Ричард Ле Мезурье
2
Это отличное решение. Если кто-то хочет знать, как переопределить заголовок не только перед тем, как элемент выбран, но и всегда, в вызове getView (), просто всегда возвращайте getNothingSelectedView (или любое другое пользовательское представление). В раскрывающемся списке по-прежнему будут отображаться элементы из вашего адаптера, но теперь вы можете контролировать заголовок ПОСЛЕ того, что что-то выбрано.
OldSchool4664
6
Это действительно элегантное решение проблемы, которой не должно быть (попробуйте разработку для Iphone). Отлично и спасибо! Рад, что кто-то вспомнил шаблоны и т. Д.
user1700737
3
@prashantwosti, код был обновлен для работы с Lollipop. В частности, getItemViewType () и getViewTypeCount ().
aaronvargas
3
@aaronvargas, однажды выбрав предмет из вертушки, можно ли отменить и выбрать «[Выбрать планету]»?
modabeckham,
130

Я закончил тем, что использовал Buttonвместо этого. Хотя a Buttonне является a 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();
}

И это все!

HRJ
источник
10
Я согласен с этим ответом. Кроме того, кнопка гораздо проще в стиле, чем Spinner.
Ромен Пиль
@ HRJ Я реализовал предложенный вами способ, но выбранный ранее элемент не выделяется (означает, что радиокнопка должна быть выделена зеленой точкой посередине) .... Как я могу добиться этого в методе OnClick () кнопка. Пожалуйста, помогите мне HRJ .....
Авадхани Y
2
Кнопка с таким макетом идеально подходит <Button android: id = "@ + id / city" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: layout_margin = "5dp" android: gravity = "left" android: background = "@ android: drawable / btn_dropdown" android: text = "@ string / city_prompt" />
kml_ckr
Как бы вы обновили текст кнопки, чтобы отразить выделение, как это было бы в блесне?
Шим
3
решение проблемы: просто вместо SetAdapter используйте SetSingleChoiceItems
Grzegorz Dev
67

Во-первых, вас может заинтересовать promptатрибут Spinnerкласса. См. Рисунок ниже: «Выберите планету» - это приглашение, которое можно задать в XML с помощью android:prompt="".

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

Я собирался предложить подкласс Spinner, где вы могли бы поддерживать два адаптера внутри. Один адаптер с опцией «Выбрать один», а другой - реальный адаптер (с актуальными опциями), затем с помощью OnClickListenerпереключателя адаптеров перед отображением диалогового окна выбора. Однако после попытки реализовать эту идею я пришел к выводу, что вы не можете получать OnClickсобытия для самого виджета.

Вы могли бы обернуть счетчик в другое представление, перехватить щелчки на представлении, а затем попросить CustomSpinnerпереключить адаптер, но это похоже на ужасный хак.

Вам действительно нужно показать «Выбрать один»?

Casey
источник
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);
Manos
источник
getItem(getCount())для меня подчеркнуто красным? Не удается разрешить метод setHint
Zapnologica
Я сомневаюсь, видел много решений в этой теме .. но почему все добавляют подсказку к последнему. Это неправильно, чтобы добавить подсказку в первом ряду?
akashPatra
Я не могу установить 'setOnItemSelectedListener (this);' потому что я использую 'реализует NavigationView.OnNavigationItemSelectedListener', я могу удалить 'setOnItemSelectedListener (this);' без проблем?
CGR
@akashpatra Причина, по которой они добавляют подсказку к последнему, заключается в том, что ArrayAdapter для spinner может получать свои значения из разных источников во время выполнения.
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] с помощью «Select One», а затем в onItemSelected переименуйте его в «One».

Не классное решение, но оно работает: 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методе
Яков Моспан
@YakivMospan Я получаю NPE, когда использую это, вероятно, из-за отражения при использовании ProGuard. Вы знаете, как это исправить?
Алан
17

Здесь много ответов, но я удивлен, что никто не предложил простое решение: поместите TextView поверх Spinner. Установите прослушиватель щелчков на TextView, который скрывает TextView, показывает Spinner и вызывает spinner.performClick ().

mjancola
источник
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
7

Вы можете изменить его на текстовое представление и использовать это:

android:style="@android:style/Widget.DeviceDefault.Light.Spinner"

а затем определить android:textсвойство.

Кристиан Вьельма
источник
Работает только для API 14 и выше.
Джулио Пьянкастелли
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");

Теперь у вас есть пустой счетчик, и вы можете написать код, чтобы не открывать диалоговое окно, если оно пустое. Или они могут нажать назад. Но вы также заполняете его функцией или другим списком во время выполнения.

trgraglia
источник
Также нет необходимости notifyDataSetChanged (), так как он должен быть установлен в true по умолчанию.
trgraglia
4

Я пытался, как следующее. Возьмите кнопку и передайте ей событие нажатия. Изменяя фон кнопки, она кажется вращающейся.

Объявите как глобальные переменные alerttdialog и значение по умолчанию.

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
Кабезас
источник
это открывает счетчик в нижней позиции
SpyZip
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>

В strings.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

wildnove
источник
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 # эквивалент ответа aaronvargas выше.

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;
    }
  }
}
MPavlak
источник
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 Spinner. Так что вам придется использовать какой-то адаптер. Так что здесь я буду использовать 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

Я справляюсь с этим, используя кнопку вместо Spinner. У меня есть пример проекта на 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, все готово.

SBerg413
источник
0

если вы столкнулись с этой проблемой, когда ваши элементы заполняются из базы-курсора ,

самое простое решение, которое я нашел в этом SO ответе:

используйте UNION в запросе адаптера курсора и добавьте дополнительный элемент с id = -1 к результату запроса, не добавляя его в базу данных:

что-то вроде:

db.rawQuery ("ВЫБЕРИТЕ iWorkerId как _id, nvLastName как имя ИЗ РАБОТНИКА w UNION SELECT -1 как _id," 'как имя ", null);

если выбранный элемент равен -1, то это значение по умолчанию. В противном случае это запись из таблицы.

dvrm
источник
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);
    }
Rako
источник
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);
}
Sayka
источник
0

Обратитесь к одному из приведенных выше ответов: https://stackoverflow.com/a/23005376/1312796

Я добавил свой код, чтобы исправить небольшую ошибку. Это где данные не получены .. Как показать текст подсказки ..!

Вот мой трюк ... Он прекрасно работает со мной. !

Попытайтесь поместить ваш счетчик в Relative_layouta и выровнять Textview с вашим счетчиком и играть с видимостью Textview (ПОКАЗАТЬ / СКРЫТЬ) всякий раз, когда адаптер счетчика загружен или пуст.

<?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);
    }

}
Ибрагим АбдельГавад
источник