Android Spinner: évitez les appels onItemSelected lors de L'initialisation
j'ai créé L'application Android avec un Spinner
et un TextView
. Ma tâche est d'afficher l'élément sélectionné dans la liste déroulante de Spinner dans TextView. J'ai implémenté Spinner dans la méthode onCreate
donc quand j'exécute le programme, il affiche une valeur dans TextView
(avant de sélectionner un élément dans la liste déroulante).
je veux afficher la valeur dans le TextView seulement après avoir sélectionné un élément de la liste déroulante. Comment dois-je faire?
Voici mon code:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
public class GPACal01Activity extends Activity implements OnItemSelectedListener {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner spinner = (Spinner) findViewById(R.id.noOfSubjects);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.noofsubjects_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
TextView textView = (TextView) findViewById(R.id.textView1);
String str = (String) parent.getItemAtPosition(pos);
textView.setText(str);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
11 réponses
spinner.setOnItemSelectedListener(this); // Will call onItemSelected() Listener.
donc pour la première fois gérer cela avec n'importe quelle valeur entière
exemple:
Prendre Initialement int check = 0;
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
if(++check > 1) {
TextView textView = (TextView) findViewById(R.id.textView1);
String str = (String) parent.getItemAtPosition(pos);
textView.setText(str);
}
}
vous pouvez le faire avec la valeur booléenne et aussi en vérifiant les positions actuelles et précédentes. voir ici
mettez juste cette ligne avant OnItemSelectedListener
spinner.setSelection(0,false)
passant false
comme second paramètre permet de régler la sélection sans animer le changement. L'animation causera un retard dans le réglage de la valeur, ce qui peut conduire à des résultats inattendus. À savoir, définir un écouteur après avoir défini la valeur initiale entraînera l'écouteur de sélection d'item recevant la sélection même si la sélection est définie avant l'auditeur est réglé.
à partir du niveau 3 de L'API, vous pouvez utiliser onUserInteraction() sur une activité avec un booléen pour déterminer si l'utilisateur interagit avec le périphérique.
http://developer.android.com/reference/android/app/Activity.html#onUserInteraction ()
@Override
public void onUserInteraction() {
super.onUserInteraction();
userIsInteracting = true;
}
Comme un champ sur l'Activité que j'ai:
private boolean userIsInteracting;
enfin, mon spinner:
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) {
}
});
Comme vous d'aller et venir grâce à l'activité le booléen est réinitialisé à false. Fonctionne comme un charme.
cela a fonctionné pour moi
L'initialisation de Spinner dans Android est parfois problématique le problème a été résolu par ce modèle.
Spinner.setAdapter();
Spinner.setSelected(false); // must
Spinner.setSelection(0,true); //must
Spinner.setonItemSelectedListener(this);
L'adaptateur de réglage doit être la première partie et onitemseletedlistener(ceci) sera la dernière lors de l'initialisation d'un tournant. Par le motif au-dessus de mon onitemselected() n'est pas appelé lors de l'initialisation de spinner
haha...J'ai la même question. Quand initViews () fait juste comme ça.La séquence est la clé, l'auditeur est le dernier. Bonne Chance !
spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
ma solution:
protected boolean inhibit_spinner = true;
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int pos, long arg3) {
if (inhibit_spinner) {
inhibit_spinner = false;
}else {
if (getDataTask != null) getDataTask.cancel(true);
updateData();
}
}
vous pouvez le faire de cette façon:
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//set the text of TextView
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
yourSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
yourSpinner.setOnItemSelectedListener(listener);
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
d'abord je crée un auditeur et l'attribue à une variable callback; ensuite je crée un second auditeur anonyme et quand cela est appelé pour la première fois, cela change l'auditeur = ]
solution simple similaire qui permet plusieurs tourneurs est de mettre L'AdapterView dans une collection - dans les activités superclass - sur la première exécution de onItemSelected(...) Vérifiez ensuite si L'AdapterView est dans la collection avant de l'exécuter. Cela permet un ensemble de méthodes dans le superclass et soutient des AdapterViews multiples et donc plusieurs browners.
super-classe ...
private Collection<AdapterView> AdapterViewCollection = new ArrayList<AdapterView>();
protected boolean firstTimeThrough(AdapterView parent) {
boolean firstTimeThrough = ! AdapterViewCollection.contains(parent);
if (firstTimeThrough) {
AdapterViewCollection.add(parent);
}
return firstTimeThrough;
}
sous-classe ...
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (! firstTimeThrough(parent)) {
String value = safeString(parent.getItemAtPosition(pos).toString());
String extraMessage = EXTRA_MESSAGE;
Intent sharedPreferencesDisplayIntent = new Intent(SharedPreferencesSelectionActivity.this,SharedPreferencesDisplayActivity.class);
sharedPreferencesDisplayIntent.putExtra(extraMessage,value);
startActivity(sharedPreferencesDisplayIntent);
}
// don't execute the above code if its the first time through
// do to onItemSelected being called during view initialization.
}
Eu le même problème et cela fonctionne pour moi:
j'ai 2 spinners et je les mets à jour pendant init et pendant les interactions avec d'autres commandes ou après avoir obtenu des données du serveur.
Voici mon modèle:
public class MyClass extends <Activity/Fragment/Whatever> implements Spinner.OnItemSelectedListener {
private void removeSpinnersListeners() {
spn1.setOnItemSelectedListener(null);
spn2.setOnItemSelectedListener(null);
}
private void setSpinnersListeners() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
spn1.setOnItemSelectedListener(MyClass.this);
spn2.setOnItemSelectedListener(MyClass.this);
}
}, 1);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Your code here
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
lorsque la classe commence à utiliser setSpinnersListeners () au lieu de régler directement l'auditeur.
le Runnable empêchera le spinner de tirer sur onItemSelected juste après que vous définissez leurs valeurs.
si vous devez mettre à jour le spinner (après un appel serveur, etc.) utilisez removeSpinnersListeners () juste avant vos lignes de mise à jour, et setSpinnersListeners () juste après les lignes de mise à jour. Cela empêchera onItemSelected de tirer après la mise à jour.
le drapeau d'interaction utilisateur peut alors être réglé à true dans la méthode onTouch et réinitialisé dans onItemSelected()
une fois que le changement de sélection a été manipulé. Je préfère cette solution parce que le drapeau d'interaction utilisateur est manipulé exclusivement pour le spinner, et non pour d'autres vues dans l'activité qui peuvent affecter le comportement désiré.
dans le code:
créez votre auditeur pour le fileur:
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) {
userSelect = false;
// Your selection handling code here
}
}
}
ajouter l'auditeur à de la toupie à la fois comme un OnItemSelectedListener
et un OnTouchListener
:
SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
, Vous pouvez l'atteindre par setOnTouchListener d'abord, puis setOnItemSelectedListener dans onTouch
@Override
public boolean onTouch(final View view, final MotionEvent event) {
view.setOnItemSelectedListener(this)
return false;
}