Вопрос по android – Spinner: onItemSelected не вызывается, когда выбранный элемент остается тем же

44

у меня естьOnItemSelectedListener для меняSpinner, но он не вызывается, когда выбранный элемент совпадает с предыдущим. ВидимоOnClickListener не вариант дляSpinner. I need to catch everytime a user click on an item. Any idea?

Может быть, тот факт, что этоSpinner находится внутриActionBar мешает нормальному поведению?

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.tracklist_menu, menu);
    Spinner spinner = (Spinner) menu.findItem(R.id.option_ordering_spinner)
            .getActionView();
    spinner.setAdapter(mSpinnerAdapter);
    spinner.setSelection(PrefsHelper.getOrderingSpinnerPos(prefs));
    spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view,
                int position, long id) {
            String str = "selected";
            System.out.println(str);
            if (optionMenuInitialized) {

                switch (position) {
                case 0:
                    // rdm
                    getActivity()
                            .sendBroadcast(
                                    new Intent(
                                            MyIntentAction.DO_RESHUFFLE_PLAYLIST));
                    smp.setCurrentTracklistCursorPos(-1);
                    trackAdapter.notifyDataSetChanged();
                    break;
                case 1:
                    // artist
                    getActivity()
                            .sendBroadcast(
                                    new Intent(
                                            MyIntentAction.DO_ORDER_PLAYLIST_BY_ARTIST));
                    smp.setCurrentTracklistCursorPos(-1);
                    trackAdapter.notifyDataSetChanged();
                    break;
                case 2:
                    // folder
                    getActivity()
                            .sendBroadcast(
                                    new Intent(
                                            MyIntentAction.DO_ORDER_PLAYLIST_BY_FOLDER));
                    smp.setCurrentTracklistCursorPos(-1);
                    trackAdapter.notifyDataSetChanged();
                    break;
                }
                PrefsHelper.setOrderingSpinnerPos(prefEditor, position);
                prefEditor.commit();
            }
            optionMenuInitialized = true;
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    });
}
Вы читаете этот постstackoverflow.com/questions/3928071/… Zain Ali
да, и это не помогло ... во всяком случае, я только что нашел решение, и собираюсь записать его здесь =) elgui

Ваш Ответ

6   ответов
18

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

  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 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());
    }
  }
}
Этот тоже работает для меня, принятый ответ не
это замечательно !!! работает нормально для меня
Вы получите NPE, если нетOnItemSelectedListener установлен и выбран тот же элемент.
1

spinner.performItemClick (вид, положение, идентификатор)

81

я наконец нашел решение, создав собственный класс, расширяющий Spinner:

public class MySpinner extends Spinner {
OnItemSelectedListener listener;

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

@Override
public void setSelection(int position) {
    super.setSelection(position);
    if (listener != null)
        listener.onItemSelected(null, null, position, 0);
}

public void setOnItemSelectedEvenIfUnchangedListener(
        OnItemSelectedListener listener) {
    this.listener = listener;
}
}
@ benoffi7 Где твой ответ?
Можете ли вы поделиться некоторыми мыслями о том, как добиться такой же функциональности для списка навигации ActionBar?
смотри мой ответ. Ваш код не работает для меня.
@dhams Извините, я ошибся с ответом и удалил его.
Как получить родителя и просмотреть в listener.onItemSelected (null, null, position, 0) ;?
2

правильный вызов обратного вызова должен быть

@Override
public void setSelection(int position) {
    super.setSelection(position);
    if(listener != null)
        listener.onItemSelected(this, getChildAt(position), position, 0);
}

Мартин

Нет, вы не правы. Например, у прядильщика есть 100 предметов, последний нажат. Но там всего 10 видимых. В этом случае,getChildAt() всегда будет возвращать ноль с 99 позициями, потому что у него нет 100 дочернихViews, Вы не можете положиться наgetChildAt() с любымAdapterViews. Вы могли бы позвонитьonItemSelected(this, getSelectedView(), position, getItemIdAtPosition(position));.
Вы правы в отношении последнего параметра для получения правильного идентификатора. Но чтобы получить представление, можно использовать getChildAt (), так как мы получаем либо правильное представление, если оно существует, либо null, если это не так. В большинстве случаев код вызывается, когда по элементу щелкают и, следовательно, он виден в счетчике, поэтому getChildAt () возвращает правильное представление. По крайней мере, я никогда не сталкивался с ситуацией, когда возвращалось неправильное представление.
Это не правильный обратный вызов. Во-первых, вы должны использоватьgetItemIdAtPosition(position) как последний параметр, на второмgetChildAt(position) не следует использовать в этом случае.SpinnerиспользованиеView переработка так же, какListViewс, такgetChildAt не может использоваться для извлечения позиции элемента из адаптера.
Может быть, я ошибаюсь, но вы хотите сказать, что getChildAt () возвращает только представления для индекса 0-9 (для 10 видимых элементов)? Я не пытался, но это звучит странно. Я ожидал бы, что он должен возвращать представление из нижележащего адаптера для всех элементов в адаптере - более конкретно, он должен возвращать представление, если оно является видимым или нулевым, когда это не так. Я постараюсь, когда у меня будет свободное время, которого у меня сейчас нет. Спиннер с 100 предметами (индекс 0-99) вернет ноль, когда я нажму 100-й предмет (поз. 99)? Я не понимаю. Когда я щелкаю последний элемент, он должен быть видимым, а getChildAt (99) должен возвращать его. Или нет?
Знаете ли вы оview recycling? НетViews для каждого элемента, только некоторыеViews добавляются, которые необходимы. Вот почемуgetChild(99) вернет ноль. 10 и 99 были только примерами, очевидно, это зависит от текущего сценария.
4

несмотря на значение последнего выбранного индекса, просто используйте:

spinner.setSelection(0); 

прежде чем ваш другой выбор называется

spinner.setSelection(number); 

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

5

public class SpinnerPlus extends Spinner {
    AdapterView.OnItemSelectedListener listener;

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

    @Override
    public void setSelection(int position) {
        super.setSelection(position);
        if (listener != null)
            listener.onItemSelected(this, getSelectedView(), position, 0);
    }

    public void setOnItemSelectedEvenIfUnchangedListener(
            AdapterView.OnItemSelectedListener listener) {
        this.listener = listener;
    }
}

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