Как сделать Android Spinner с начальным текстом & ldquo; Select One & rdquo ;?

public static long randomLong(long min, long max)
{
    try
    {
        Random  random  = new Random();
        long    result  = min + (long) (random.nextDouble() * (max - min));
        return  result;
    }
    catch (Throwable t) {t.printStackTrace();}
    return 0L;
}
544
задан double-beep 2 May 2019 в 06:48
поделиться

4 ответа

Вот общее решение, которое отменяет представление 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);
        }
    }
}
251
ответ дан 22 November 2019 в 22:16
поделиться

Лучшее решение, которое я нашел для этого, не состоит в том, чтобы на самом деле использовать Счетчик, но AutoCompleteTextView. В основном EditText с приложенным Счетчиком для показывания предложений, поскольку Вы вводите - но с правильной конфигурацией он может вести себя точно как пожелания OP и т.д.

XML:

<com.google.android.material.textfield.TextInputLayout
                android:id="@+id/item"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <androidx.appcompat.widget.AppCompatAutoCompleteTextView
                    android:id="@+id/input"
                    android:hint="Select one"
                    style="@style/AutoCompleteTextViewDropDown"/>
        </com.google.android.material.textfield.TextInputLayout>

Стиль:

<style name="AutoCompleteTextViewDropDown">
    <item name="android:clickable">false</item>
    <item name="android:cursorVisible">false</item>
    <item name="android:focusable">false</item>
    <item name="android:focusableInTouchMode">false</item>
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">wrap_content</item>
</style>

Что касается адаптера используют основной ArrayAdapter или расширяют его для создания собственного, но никакая дополнительная настройка на стороне адаптера не необходима. Установите адаптер на AutoCompleteTextView.

0
ответ дан Chapz 29 August 2019 в 17:53
поделиться
  • 1
    @111111: Существуют за и против. Огромный риск, который выполняет этот подход, состоит в том что shared_ptr won' t уходят, прежде чем переменная стека делает. Но it' s НАМНОГО более эффективный, чем создание копии на "куче". И ybungalobill корректен, это - единственный технически корректный ответ на вопрос, как указано. Это не заслужило downvote. – Omnifarious 11 December 2011 в 19:10

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

enter image description here

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

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

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

66
ответ дан 22 November 2019 в 22:16
поделиться

Я нашел это решение:

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

Просто измените array[0] на "Select One", а затем в onItemSelected переименуйте его в "One".

Не самое стильное решение, но оно работает :D

31
ответ дан 22 November 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: