441 Stimmen

Wie zu halten onItemSelected von Auslösen auf eine neu instanziierte Spinner?

Ich habe mir ein paar weniger elegante Lösungen überlegt, aber ich weiß, dass ich etwas übersehen muss.

Meine onItemSelected wird sofort und ohne Interaktion mit dem Benutzer ausgelöst, und das ist ein unerwünschtes Verhalten. Ich möchte, dass die Benutzeroberfläche wartet, bis der Benutzer etwas auswählt, bevor sie etwas tut.

Ich habe sogar versucht, den Hörer in der onResume() in der Hoffnung, das würde helfen, aber das tut es nicht.

Wie kann ich verhindern, dass diese Funktion ausgelöst wird, bevor der Benutzer das Steuerelement berühren kann?

public class CMSHome extends Activity { 

private Spinner spinner;

@Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Heres my spinner ///////////////////////////////////////////
    spinner = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
            this, R.array.pm_list, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
    };

public void onResume() {
    super.onResume();
    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}

    public class MyOnItemSelectedListener implements OnItemSelectedListener {

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

     Intent i = new Intent(CMSHome.this, ListProjects.class);
     i.putExtra("bEmpID", parent.getItemAtPosition(pos).toString());
        startActivity(i);

        Toast.makeText(parent.getContext(), "The pm is " +
          parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
    }

    public void onNothingSelected(AdapterView parent) {
      // Do nothing.
    }
}
}

3 Stimmen

Sie können sich diese Lösung ansehen, sie ist einfach und praktisch. stackoverflow.com/a/10102356/621951

1 Stimmen

Eine einfache Lösung wäre, den ersten Punkt in Spinner leer und innen onItemSelected können Sie erkennen, ob die Zeichenfolge nicht leer ist, dann startActivity !

0 Stimmen

Dieses Muster funktioniert richtig stackoverflow.com/questions/13397933/

32voto

Chris Punkte 4535

Ich hatte schon viele Probleme mit dem Spinner, der immer dann ansprang, wenn ich es nicht wollte, und alle Antworten hier sind unzuverlässig. Sie funktionieren - aber nur manchmal. Sie werden schließlich in Szenarien laufen, wo sie scheitern und Bugs in Ihrem Code einzuführen.

Was bei mir funktioniert hat, war, den zuletzt gewählten Index in einer Variablen zu speichern und im Listener auszuwerten. Wenn er mit dem neuen ausgewählten Index übereinstimmt, machen Sie nichts und kehren zurück, ansonsten fahren Sie mit dem Listener fort. Tun Sie dies:

//Declare a int member variable and initialize to 0 (at the top of your class)
private int mLastSpinnerPosition = 0;

//then evaluate it in your listener
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {

  if(mLastSpinnerPosition == i){
        return; //do nothing
  }

  mLastSpinnerPosition = i;
  //do the rest of your code now

}

Vertrauen Sie mir, wenn ich sage, dass dies bei weitem die zuverlässigste Lösung ist. Ein Hack, aber es funktioniert!

0 Stimmen

Funktioniert das überhaupt, wenn Sie versuchen, den Wert zu ändern? In meinem Fall versuche ich, den Wert auf etwas wie 3 zu setzen, obwohl er eigentlich 0 ist, ohne die Änderungshörer auszulösen. Sagen Sie, dass int i nur einen anderen Wert zurückgibt, wenn der Benutzer es auswählt?

0 Stimmen

Hallo JStephen, ich bin mir nicht ganz sicher, was Sie meinen. Aber int i wird die Position des Spinners sein, wenn onItemSelected ausgelöst wird. Das Problem ist, dass on

0 Stimmen

H

27voto

JASON G PETERSON Punkte 2168

Nur um Hinweise auf die Verwendung des onTouchListener zwischen automatischen Aufrufen des setOnItemSelectedListener (die Teil der Aktivitätsinitialisierung usw. sind) vs. Aufrufe zu unterscheiden, die durch tatsächliche Benutzerinteraktion ausgelöst werden, habe ich Folgendes getan, nachdem ich einige andere Vorschläge hier ausprobiert und festgestellt hatte, dass es mit den wenigsten Codezeilen gut funktioniert.

Setzen Sie einfach ein boolesches Feld für Ihre Aktivität/Fragment wie:

private Boolean spinnerTouched = false;

Dann, kurz bevor Sie Ihre Spinner's setOnItemSelectedListener, ein onTouchListener gesetzt:

    spinner.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            System.out.println("Real touch felt.");
            spinnerTouched = true;
            return false;
        }
    });

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    ...
         if (spinnerTouched){
         //Do the stuff you only want triggered by real user interaction.
        }
        spinnerTouched = false;

1 Stimmen

Das funktioniert hervorragend, und seit Android 6+ ist das die einzige Methode, die funktioniert. ABER, Sie müssen auch das gleiche mit setOnKeyListener() tun, oder es funktioniert nicht, wenn der Benutzer mit der Tastatur navigiert.

0 Stimmen

Funktioniert großartig, alle anderen Lösungen haben einige Probleme mit verschiedenen Handys.

0 Stimmen

Das ist einfach und absolut perfekt! Kein zusätzlicher Blödsinn nötig, einfach die Logik im Kopf behalten. Ich bin froh, dass ich den ganzen Weg bis hierher gescrollt habe!

26voto

Michal Punkte 543

Ich war in einer ähnlichen Situation, und ich habe eine einfache Lösung, die bei mir funktioniert.

Es scheint, dass die Methoden setSelection(int position) y setSelected(int position, boolean animate) haben unterschiedliche interne Implementierungen.

Wenn Sie die zweite Methode verwenden setSelected(int position, boolean animate) mit falscher Animationsflagge erhalten Sie die Auswahl ohne Auslösung onItemSelected Hörer.

0 Stimmen

Der bessere Ansatz ist, sich nicht um die zusätzlichen Aufrufe von onItemSelected zu kümmern, sondern sicherzustellen, dass die richtige Auswahl angezeigt wird. Also, Aufruf spinner.setSelection(selectedIndex) vor dem Hinzufügen von Listener machte es konsequent für mich arbeiten.

1 Stimmen

Es gibt keine setSelected(int position, boolean animate)-Methode für spinner

4 Stimmen

Der eigentliche Aufruf, den Sie benötigen, lautet setSelection(int position, boolean animate);

13voto

j2emanue Punkte 56131
spinner.setSelection(Adapter.NO_SELECTION, false);

4 Stimmen

Der Code mag für sich selbst sprechen, aber ein bisschen Erklärung hilft weiter :)

11voto

Uzair Punkte 1501

Dies geschieht, wenn Sie die Auswahl im Code als treffen;

   mSpinner.setSelection(0);

Anstelle der obigen Anweisung verwenden Sie

   mSpinner.setSelection(0,false);//just simply do not animate it.

Edit: Diese Methode funktioniert nicht für die Mi Android Version Mi UI.

2 Stimmen

Damit ist das Problem für mich definitiv gelöst. Ich habe die Dokumentation über das Spinner-Widget gelesen. Es ist absolut schwierig, den Unterschied zu verstehen: setSelection(int position, boolean animate) -> Springt direkt zu einem bestimmten Element in den Adapterdaten. setSelection(int position) -> Setzt das aktuell ausgewählte Element.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X