Как получить событие в Android Spinner, когда текущий выбранный элемент снова выбран? - PullRequest
53 голосов
/ 17 марта 2011

Я написал setOnItemSelectedListener для счетчика, чтобы он реагировал на изменение элемента счетчика.Мое требование - когда я снова нажимаю на выбранный элемент, должен появиться тост.Как получить это событие?При повторном щелчке по выбранному элементу спиннер не отвечает.`

    StorageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

        @Override
        public void onItemSelected(AdapterView adapter, View v, int i, long lng) {              
            Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();

        }

        @Override
        public void onNothingSelected(AdapterView arg0) {
            Toast.makeText(getApplicationContext(), "Nothing selected", Toast.LENGTH_SHORT).show();

        }
    });  

Ответы [ 19 ]

1 голос
/ 16 марта 2016
class MySpinner extends Spinner {


    public MySpinner(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public MySpinner(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    @Override
    public void setSelection(int position, boolean animate) {
        ignoreOldSelectionByReflection();
        super.setSelection(position, animate);
    }

    private void ignoreOldSelectionByReflection() {
        try {
            Class<?> c = this.getClass().getSuperclass().getSuperclass().getSuperclass();
            Field reqField = c.getDeclaredField("mOldSelectedPosition");
            reqField.setAccessible(true);
            reqField.setInt(this, -1);
        } catch (Exception e) {
            Log.d("Exception Private", "ex", e);
            // TODO: handle exception
        }
    }

    @Override
    public void setSelection(int position) {
        ignoreOldSelectionByReflection();
        super.setSelection(position);
    }

}
1 голос
/ 03 октября 2015

Поведение Spinner не ожидается для наших требований. Мое решение не работает со Spinners, сделайте его аналогичным образом, с одним ListView внутри одного BaseFragment для исследования ожидаемой нами функциональности.

Преимущества:

  1. Больше нет головных болей, расширяющих значения по умолчанию для Spinner.
  2. Простота реализации и настройки.
  3. Полная совместимость со всеми API Android.
  4. Нет лица против первого вызова OnItemSelectedListener.onItemSelected.

Основная идея, сделать что-то вроде этого:

Макет BaseFragment может выглядеть примерно так:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:background="@null"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              android:gravity="center">

    <ListView
            android:id="@+id/fragment_spinnerList"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
</LinearLayout>

Код выглядит примерно так:

public class SpinnerListFragment extends android.support.v4.app.DialogFragment {

    static SpinnerListFragment newInstance(List<String> items) {

        SpinnerListFragment spinnerListFragment = new SpinnerListFragment();
        Bundle args = new Bundle();

        args.putCharSequenceArrayList("items", (ArrayList) items);
        spinnerListFragment.setArguments(args);

        return spinnerListFragment;
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        Dialog dialog = new Dialog(getActivity(), R.style.dialog);
        final View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_spinner_list, null);

        dialog.getWindow().setContentView(view);
        dialog.setCanceledOnTouchOutside(true);

        // CUSTOMIZATION...

        final List items = (ArrayList) getArguments().getCharSequenceArrayList("items");

        final ListView spinnerList = (ListView) view.findViewById(R.id.fragment_spinnerList);

        ArrayAdapter<String> arrayAdapter =
                new ArrayAdapter<String>(
                        getActivity(),
                        R.layout.search_spinner_list_item,
                        items);

        spinnerList.setAdapter(arrayAdapter);

        spinnerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                // DO SOMETHING...

                SpinnerListFragment.this.dismiss();
            }
        });

        return dialog;
    }

}
1 голос
/ 21 ноября 2014

Мое решение основано на MySpinner от benoffi7. Исправлено пропускание пустых значений при выборе того же элемента путем сохранения последнего выбранного родителя и просмотра.

public class MySpinner extends Spinner {

    private OnItemSelectedListener listener;
    private AdapterView<?> lastParent;
    private View lastView;
    private long lastId;

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

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

    private void initInternalListener() {
        super.setOnItemSelectedListener(new OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> parent, View view,
                int position, long id) {
                lastParent = parent;
                lastView = view;
                lastId = id;
                if (listener != null) {
                    listener.onItemSelected(parent, view, position, id);
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                //lastParent = parent; // do we need it?
                if (listener != null) {
                    listener.onNothingSelected(parent);
                }
            }
        });
    }

    @Override
    public void setSelection(int position) {
        if (position == getSelectedItemPosition() && listener != null) {
            listener.onItemSelected(lastParent, lastView, position, lastId);
        } else {
            super.setSelection(position);
        }
    }

    @Override
    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
        this.listener = listener;
    }
}
1 голос
/ 26 марта 2012

Здравствуйте и спасибо @Dimitar за креативный ответ на проблему. Я попробовал это, и он хорошо работает на старых версиях Android, таких как 2.x, но, к сожалению, он не работает на версии 3.0 и выше (пробовал 3.2 и 4.0.3) По какой-то причине метод onClick никогда не вызывается на новых платформах. Кто-то написал сообщение об ошибке здесь: http://code.google.com/p/android/issues/detail?id=16245

Не работает на новых платформах означает, что мне нужно другое решение. В моем приложении было достаточно смоделировать невыбранный счетчик со скрытой «фиктивной» записью в начале. Тогда каждый нажатый элемент приведет к обратному вызову, если в качестве выбора выбран «скрытый» элемент. Недостатком для некоторых может быть то, что ничего не будет выделено, но это можно исправить, используя приемы переопределения класса Spinner.

См. Как скрыть один элемент в Android Spinner

0 голосов
/ 09 сентября 2015

, если вы действительно хотите выполнить эту задачу в своем XML, когда ваш экранный указатель добавляет один текст редактирования и устанавливает атрибут видимости ушел; и создайте адаптер костюма для прядильщика и в адаптере костюма, установленном на view.onclicklisner и при запуске clickkevent EditText.setText ("0"); и в поле активности установите текстовое событие TextWatcher, а в блоке события добавьте свой код блока события onSppinerItem; Ваша проблема решена

0 голосов
/ 30 ноября 2016
package customclasses;

/**
 * Created by Deepak on 7/1/2015.
 */

import android.content.Context;
import android.util.AttributeSet;
import android.widget.Spinner;

/**
 * Spinner extension that calls onItemSelected even when the selection is the same as its previous value
 */
public class NDSpinner extends Spinner {
    public boolean isDropDownMenuShown=false;

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

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

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


    @Override
    public void
    setSelection(int position, boolean animate) {
        boolean sameSelected = position == getSelectedItemPosition();
        super.setSelection(position, animate);
        if (sameSelected) {
            // Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
            getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
        }
    }

    @Override
    public boolean performClick() {
        this.isDropDownMenuShown = true; //Flag to indicate the spinner menu is shown
        return super.performClick();
    }
    public boolean isDropDownMenuShown(){
        return isDropDownMenuShown;
    }
    public void setDropDownMenuShown(boolean isDropDownMenuShown){
        this.isDropDownMenuShown=isDropDownMenuShown;
    }
    @Override
    public void
    setSelection(int position) {
        boolean sameSelected = position == getSelectedItemPosition();
        super.setSelection(position);
        if (sameSelected) {
            // Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
            getOnItemSelectedListener().onItemSelected(this, getSelectedView(), position, getSelectedItemId());
        }
    }
    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
    }
}
0 голосов
/ 23 июня 2011

При повторном нажатии на выбранный в данный момент элемент он не может запустить ни одно событие.Таким образом, вы не можете поймать setOnItemSelectedListener для ответчика, чтобы ответить.

0 голосов
/ 23 октября 2018

Пользовательский спиннер с таким же обратным вызовом выбора элемента в Kotlin :

class StorageSpinner : AppCompatSpinner {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    interface StorageSpinnerSelectionCallback {
        fun onItemSelected(position: Int)
    }

    private var selectionCallback: StorageSpinnerSelectionCallback? = null

    fun setSelectionCallback(selectionCallback: StorageSpinnerSelectionCallback) {
        this.selectionCallback = selectionCallback
    }

    fun removeSelectionCallback() {
        selectionCallback = null
    }

    override fun setSelection(position: Int) {
        super.setSelection(position)

        if (position == selectedItemPosition) selectionCallback?.onItemSelected(position)
    }
}
0 голосов
/ 17 марта 2011

Просто попробуйте это.

@Override
public void onItemSelected(AdapterView adapter, View v, int i, long lng) {  

    if(v.hasFocus() {            
        Toast.makeText(getApplicationContext(), (CharSequence) StorageSpinner.getSelectedItem(), Toast.LENGTH_SHORT).show();
    }    
}

Надеюсь, это сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...