it-swarm.com.de

Spinner onItemSelected wurde fälschlicherweise aufgerufen (ohne Benutzeraktion)

Ich habe einen Spinner, den ich in einer Dialogansicht zeige, und sobald der Dialog gestartet wird, wird onItemSelected aufgerufen. Ich möchte das nicht wirklich verarbeiten, sondern nur, wenn der Benutzer die Auswahl trifft. Also muss ich dies entweder verhindern (vielleicht weil es keinen Standardwert gibt?) Oder ich muss wissen, dass nicht der Benutzer diese Auswahl vornimmt.

25
Androider

Androider, ich habe eine Lösung für dieses Problem gefunden und es hier gepostet (mit Codebeispiel): 

Spinner onItemSelected () wird ausgeführt, wenn nicht angenommen wird, dass

6

Eine weitere Option im Sinne von Bill Motes Lösung besteht darin, aus der OnItemSelectedListener auch eine OnTouchListener zu machen. Das Benutzerinteraktionsflag kann dann in der onTouch-Methode auf true gesetzt und in onItemSelected() zurückgesetzt werden, sobald die Auswahländerung behandelt wurde. Ich bevorzuge diese Lösung, weil das Benutzerinteraktionsflag ausschließlich für den Spinner und nicht für andere Ansichten in der Aktivität gehandhabt wird, die das gewünschte Verhalten beeinflussen können. 

In Code:

Erstellen Sie Ihren Listener für den Spinner:

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) { 
            // Your selection handling code here
            userSelect = false;
        }
    }

}

Fügen Sie dem Spinner den Listener als OnItemSelectedListener und OnTouchListener hinzu:

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
41
Andres Q.

Sie können einfach eine int-Anzahl hinzufügen, um sie zu lösen :)

 sp.setOnItemSelectedListener(new OnItemSelectedListener() {
    int count=0;
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
        if(count >= 1){
            int item = sp.getSelectedItemPosition();
            Toast.makeText(getBaseContext(),
                 "You have selected the book: " + androidBooks[item],
                  Toast.LENGTH_SHORT).show();
        }
        count++;
    }


    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
    }
});
21

Ab API Level 3 können Sie onUserInteraction () für eine Activity mit einem Boolean verwenden, um festzustellen, ob der Benutzer mit dem Gerät interagiert.

http://developer.Android.com/reference/Android/app/Activity.html#onUserInteraction ()

@Override
public void onUserInteraction() {
    super.onUserInteraction();
    userIsInteracting = true;
}

Als Feld auf der Aktivität habe ich:

private boolean userIsInteracting;

Zum Schluss mein 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) {

        }
    });

Wenn Sie kommen und die Aktivität durchlaufen, wird der Boolean auf false zurückgesetzt. Klappt wunderbar.

8
Bill Mote

Ich habe dieses Problem auf eine andere Weise gelöst, da ich manchmal bemerkte, dass die Methode onItemSelected zweimal bei einer Orientierungsänderung oder manchmal einmal aufgerufen wurde.

Es schien von der aktuellen Auswahl der Spinner abzuhängen. Also funktionierte eine Flagge oder ein Schalter nicht für mich. Stattdessen zeichne ich die Systemzeit in BEIDE onResume () und onCreate mit WidgetsRestartTime = System.currentTimeMillis () auf.

widgetsRestartTime wird als double und als intance-Variable deklariert.

Jetzt prüfe ich in der onItemSelected () - Methode erneut die aktuelle Uhrzeit und subtrahiere widgetsRestartTime wie folgt: If (System.currentTimeMillis () - widgetsRestartTime> 200) { // Benutzer ausgelöstes Ereignis - Dies ist also ein echtes Spinnerereignis, so dass es } sonst { // verarbeitet wird Orientierungsänderung, Aktivitätsstart. ignoriere also }

4
karl

Ich hatte das gleiche Problem. Die akzeptierte Lösung funktionierte jedoch nicht für mich, da ich mehrere Spinner in meinem Formular habe. Einige davon sind versteckt. Wenn die Spinner ausgeblendet sind, feuert der Zuhörer nicht. Daher ist das Zählen keine Lösung für mich.

Ich habe eine andere Lösung gefunden obwohl:

  1. Setze ein Standard-TAG während der Initialisierung, in onCreate () deiner Aktivität oder onCreateView deines Fragments und vor dem Setzen des Listeners
  2. Überprüfen Sie im Listener das Tag (sofern vorhanden), löschen Sie es und führen Sie den Code nicht aus, indem Sie zurückkehren.

Das ist es, es funktioniert wie ein Zauber!

Beispiel im Listener:

        if(((String)parent.getTag()).equalsIgnoreCase(TAG_SPINNERVALUE))
        {
            parent.setTag("");
            return;
        }

P.S. Und das funktioniert für den gleichen Listener, der auf mehrere Spinner eingestellt ist!

3
XMight

Ja, was Sie sehen, ist korrekt und ist das Standardverhalten. Sie können dies nicht verhindern. Der OnItemSelected-Callback wird beim ersten Laden aufgerufen. Nach diesem ersten Laden wird es nur ausgelöst, wenn der Benutzer die Auswahl ändert oder wenn Sie die Auswahl innerhalb Ihres Codes ändern. Sie können über ein Kennzeichen verfügen, das Sie darüber informiert, ob das Ereignis ein Ergebnis der Erstladung war, und das erste Ereignis ignorieren, wenn Sie es nicht verarbeiten möchten. 

3
Veeresh

Ich hatte das gleiche Problem und löste es, indem ich mich an den zuvor ausgewählten Spinnerwert erinnerte. Bei jedem Aufruf von onItemSelected vergleiche ich den neuen Wert mit dem vorherigen, und wenn er identisch ist, verarbeite ich den Code nicht weiter. 

3
Shumoapp

Wenn Sie auch einen zunächst nicht ausgewählten Spinner kaufen, können Sie mit gehen

@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
    if(pos != 0) {
        pos--;

        // your code here
    }
}

Da Artikel 0 niemals ausgewählt werden kann. Prost :-)

2
ThomasRS

Es hat für mich funktioniert,

private boolean isSpinnerInitial = true;

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

    if(isSpinnerInitial)
    {
        isSpinnerInitial = false;
    }
    else  {
        // do your work...
    }

}
2
karan

Sie sollten es so machen. Die Reihenfolge ist der Schlüssel.

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
1
Treesouth

Ich habe auch im Internet nach einer guten Lösung gesucht, aber keine gefunden, die meine Bedürfnisse befriedigt. Ich habe diese Erweiterung in der Spinner-Klasse geschrieben, sodass Sie einen einfachen OnItemClickListener festlegen können, der das gleiche Verhalten aufweist als ListView. 

Nur wenn ein Element ausgewählt wird, wird der onItemClickListener aufgerufen. 

Viel Spass damit!

public class MySpinner extends Spinner
{
    private OnItemClickListener onItemClickListener;


    public MySpinner(Context context)
    {
        super(context);
    }

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

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

    @Override
    public void setOnItemClickListener(Android.widget.AdapterView.OnItemClickListener inOnItemClickListener)
    {
        this.onItemClickListener = inOnItemClickListener;
    }

    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        super.onClick(dialog, which);

        if (this.onItemClickListener != null)
        {
            this.onItemClickListener.onItemClick(this, this.getSelectedView(), which, this.getSelectedItemId());
        }
    }
}
1
Cliffus

Wenn es Ihnen nichts ausmacht, eine Position für Promt zu verwenden, können Sie dies jedes Mal tun, wenn Sie Mitarbeiter am Spinner sind. Erste Auswahl auf das Promt setzen:

spinner.setselected(0);
spinner.add("something");
...

Und dann machen Sie so etwas, wenn die Auswahl geschieht:

spinner.ItemSelected += (object sender, AdapterView.ItemSelectedEventArgs e) => 
            {
                if (spinner.SelectedItemPosition != 0)
                {
                   //do staff
                } 
            }
0
CDrosos

Sie können versuchen, den Spinner mit zwei Argumenten wie folgt einzustellen:

spinner.setSelection(count, false);

Setzen Sie das also vor den OnItemSelectedListener:

spinner.setSelection(0,false);

Sie können mehr auf der Entwicklerseite überprüfen:

https://developer.Android.com/reference/Android/widget/Spinner.html

0
Carlos Ughini