J'ai un OnItemSelectedListener
pour mon Spinner
, mais il n'est pas appelé lorsque l'élément sélectionné est le même que le précédent. Apparemment, le OnClickListener
n'est pas une option pour un Spinner
. Je dois attraper chaque fois qu'un utilisateur clique sur un élément. Une idée?
Peut-être que le fait que ce Spinner
soit à l'intérieur du ActionBar
perturbe un comportement normal?
@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) {
}
});
}
Ok, j'ai finalement trouvé une solution, en créant ma propre classe étendant 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;
}
}
J'ai découvert ce travail au lieu de celui fourni
/** 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());
}
}
}
Pour faire changer votre spinner malgré la valeur du dernier index sélectionné, utilisez simplement:
spinner.setSelection(0);
avant d'appeler votre autre sélection
spinner.setSelection(number);
de cette façon, le spinner déclenchera deux fois l'événement OnItemSelected. Assurez-vous simplement que la deuxième fois, il fait tout ce dont vous avez besoin.
Voici une mise en œuvre un peu meilleure:
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;
}
}
S'il est toujours réel, l'appel correct du rappel doit être
@Override
public void setSelection(int position) {
super.setSelection(position);
if(listener != null)
listener.onItemSelected(this, getChildAt(position), position, 0);
}
Martin
Solution la plus simple:
spinner.performItemClick (vue, position, id)
J'ai eu le même problème, je l'ai résolu en définissant onItemSelectedListener à chaque fois que l'adaptateur change d'élément.
Réécriture de la solution commune mais avec:
AppCompatSpinner
OnItemSelectedListener
intégré au lieu d'en créer unIci:
import Android.content.Context;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatSpinner;
public class FixedSpinner extends AppCompatSpinner {
// add other constructors that you need
public FixedSpinner(Context context, int mode) {
super(context, mode);
}
private void processSelection(int position) {
boolean sameSelected = position == getSelectedItemPosition();
final OnItemSelectedListener listener = getOnItemSelectedListener();
if (sameSelected && listener != null) {
// Spinner does not call the OnItemSelectedListener if the same item is selected, so do it manually now
listener.onItemSelected(this, getSelectedView(), position, getSelectedItemId());
}
}
@Override
public void setSelection(int position) {
processSelection(position);
super.setSelection(position);
}
@Override
public void
setSelection(int position, boolean animate) {
processSelection(position);
super.setSelection(position, animate);
}
@Override
public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) {
// hack for initial listener call
setSelection(0, false);
super.setOnItemSelectedListener(listener);
}
}