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

    }
}
86
demandé sur Pratik Butani 2012-11-15 16:55:23

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

127
répondu Abhi 2017-05-23 12:02:23

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é.

53
répondu Dayanand Waghmare 2018-09-27 19:57:39

à 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.

45
répondu Bill Mote 2014-07-31 23:42:09

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

11
répondu saksham 2017-06-23 07:53:30

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);
10
répondu Treesouth 2015-03-14 01:26:38

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();
            }

        }
7
répondu codareee 2013-09-23 15:32:24

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 = ]

5
répondu Charleston 2014-06-11 02:30:05

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.

}

2
répondu Jonathan Cole 2013-07-18 22:25:26

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.

1
répondu RoyBS 2015-10-22 15:04:33

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);
1
répondu Ranjith Kumar 2017-03-07 03:39:59

, 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;
}
0
répondu vviieett 2015-11-19 08:06:11