Spinner onItemSelected вызван по ошибке (без действий пользователя) - PullRequest
25 голосов
/ 26 февраля 2011

У меня есть счетчик, который я показываю в диалоговом окне, и в момент запуска диалога onItemSelected вызывается. Я действительно не хочу обрабатывать это, но только когда пользователь делает выбор. Поэтому мне либо нужно это предотвратить (может быть, потому что не задано значение по умолчанию?), Либо мне нужно знать, что это не тот пользователь, который делает этот выбор?

Ответы [ 14 ]

41 голосов
/ 12 февраля 2015

Другой вариант в духе решения Билла Моте - сделать OnItemSelectedListener также OnTouchListener.Затем флаг взаимодействия с пользователем может быть установлен в true в методе onTouch и сброшен в onItemSelected() после обработки изменения выбора.Я предпочитаю это решение, потому что флаг взаимодействия с пользователем обрабатывается исключительно для счетчика, а не для других представлений в действии, которые могут повлиять на желаемое поведение.

В коде:

Создайте слушателя для счетчика:

public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {

    boolean userSelect = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        userSelect = true;
        return false;
    }

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
        if (userSelect) { 
            // Your selection handling code here
            userSelect = false;
        }
    }

}

Добавьте слушателя к счетчику как OnItemSelectedListener и OnTouchListener:

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
21 голосов
/ 11 апреля 2012

Вы можете просто добавить счетчик целых чисел, чтобы решить его:)

 sp.setOnItemSelectedListener(new OnItemSelectedListener() {
    int count=0;
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if(count >= 1){
            int item = sp.getSelectedItemPosition();
            Toast.makeText(getBaseContext(),
                 "You have selected the book: " + androidBooks[item],
                  Toast.LENGTH_SHORT).show();
        }
        count++;
    }


    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});
8 голосов
/ 01 августа 2014

Начиная с уровня API 3, вы можете использовать onUserInteraction () для Activity с логическим значением, чтобы определить, взаимодействует ли пользователь с устройством.

http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    userIsInteracting = true;
}

В качестве поля в Деятельности у меня есть:

private boolean userIsInteracting;

Наконец, мой счетчик:

    mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
            spinnerAdapter.setmPreviousSelectedIndex(position);
            if (userIsInteracting) {
                updateGUI();
            }
        }

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

        }
    });

Когда вы приходите и проходите действие, логическое значение сбрасывается в false. Работает как шарм.

6 голосов
/ 07 мая 2011

Androider, я нашел решение этой проблемы и разместил его здесь (с примером кода):

Spinner onItemSelected () выполняется, когда не предполагается,

4 голосов
/ 28 октября 2011

Я решил эту проблему по-другому, так как заметил, что метод onItemSelected иногда вызывался дважды при изменении ориентации, а иногда один раз.

Кажется, это зависит от текущего выбора счетчика. Таким образом, флаг или счетчик не работает для меня. Вместо этого я записываю системное время в ОБА onResume () и onCreate, используя widgetsRestartTime = System.currentTimeMillis ()

widgetsRestartTime объявлен как double и как переменная intance.

Теперь в методе onItemSelected () я снова проверяю текущее время и вычитаю из него widgetsRestartTime следующим образом: if (System.currentTimeMillis () - widgetsRestartTime> 200) { // событие, инициируемое пользователем - так что это настоящее вращающееся событие, поэтому обработайте его } еще { // событие, сгенерированное системой, например изменение ориентации, запуск активности. так что игнорируй }

3 голосов
/ 02 июля 2012

У меня была такая же проблема. Но принятое решение не сработало для меня, потому что у меня в форме несколько счетчиков, и некоторые из них скрыты, а когда счетчики скрыты, слушатель не запускается, поэтому подсчет не является решением для меня.

Я нашел другое решение хотя:

  1. Установите TAG по умолчанию на счетчике при его инициализации, в onCreate () вашей деятельности или onCreateView вашего фрагмента, а также перед настройкой слушателя
  2. В прослушивателе проверьте тег, если он присутствует, затем удалите его и не выполняйте код, вернув.

Вот и все, это работает как шарм!

Пример в слушателе:

        if(((String)parent.getTag()).equalsIgnoreCase(TAG_SPINNERVALUE))
        {
            parent.setTag("");
            return;
        }

P.S. И это работает для одного и того же слушателя с несколькими вращателями!

3 голосов
/ 18 мая 2012

У меня была та же проблема, и я решил ее, запомнив предыдущее выбранное значение счетчика. При каждом вызове onItemSelected я сравниваю новое значение с предыдущим, и если оно совпадает, я не обрабатываю код дальше.

3 голосов
/ 26 февраля 2011

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

2 голосов
/ 21 января 2015

у меня сработало,

private boolean isSpinnerInitial = true;

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

    if(isSpinnerInitial)
    {
        isSpinnerInitial = false;
    }
    else  {
        // do your work...
    }

}
2 голосов
/ 23 июня 2013

Если вы также покупаете изначально невыбранный Spinner , вы можете выбрать

@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    if(pos != 0) {
        pos--;

        // your code here
    }
}

, так как элемент 0 выбрать невозможно.Приветствия: -)

...