web-dev-qa-db-de.com

Android-Spinner: Vermeiden Sie Anrufe, die während der Initialisierung ausgewählt werden

Ich habe eine Android-Anwendung mit einer Spinner und einer TextView erstellt. Meine Aufgabe ist es, das ausgewählte Element aus der Dropdown-Liste des Spinners in der Textansicht anzuzeigen. Ich habe den Spinner in der onCreate-Methode implementiert. Wenn ich das Programm ausführe, wird in der TextView ein Wert angezeigt (bevor ein Element aus der Dropdown-Liste ausgewählt wird). 

Ich möchte den Wert nur in der Textansicht anzeigen, nachdem Sie ein Element aus der Dropdown-Liste ausgewählt haben. Wie mache ich das?

Hier ist mein 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

    }
}
104
Grant
spinner.setOnItemSelectedListener(this); // Will call onItemSelected() Listener.

Behandeln Sie dies beim ersten Mal mit einem beliebigen Integer-Wert

Beispiel: Nehmen Sie zunächst 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);
   }
}

Sie können dies mit einem booleschen Wert tun und auch die aktuellen und vorherigen Positionen prüfen. Siehe hier

139
Abhi

Setzen Sie diese Zeile einfach vor set OnItemSelectedListener

spinner.setSelection(0,false)
70

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.

49
Bill Mote

Das hat bei mir funktioniert 

Die Initialisierung des Spinners in Android ist manchmal problematisch. Das obige Problem wurde durch dieses Muster gelöst.

Spinner.setAdapter();
Spinner.setSelected(false);  // must
Spinner.setSelection(0,true);  //must
Spinner.setonItemSelectedListener(this);

Der Einstellungsadapter sollte der erste Teil sein, und onItemSelectedListener (this) ist der letzte, wenn ein Spinner initialisiert wird. Durch das Muster oben wird mein OnItemSelected () während der Initialisierung des Spinners nicht aufgerufen

12
saksham

haha ... Ich habe die gleiche Frage . Wenn initViews () einfach so macht. Die Sequenz ist der Schlüssel, Listener ist der letzte. Viel Glück !

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

Meine Lösung:

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
codareee

Sie können dies auf folgende Weise tun:

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) {

        }
    });

Zuerst erstelle ich einen Listener und wird einem variablen Callback zugeordnet. dann erstelle ich einen zweiten Listener anonym und wenn dieser zum ersten Mal aufgerufen wird, ändern Sie den Listener =]

5
Charleston

Eine ähnliche einfache Lösung, die mehrere Spinner ermöglicht, besteht darin, die AdapterView bei der ersten Ausführung von onItemSelected (...) in eine Collection aufzunehmen - in der Superklasse Activities (...). Dies ermöglicht einen Satz von Methoden in der Superklasse und unterstützt mehrere AdapterViews und somit mehrere Spinner.

Oberklasse ...

private Collection<AdapterView> AdapterViewCollection = new ArrayList<AdapterView>();

   protected boolean firstTimeThrough(AdapterView parent) {
    boolean firstTimeThrough = ! AdapterViewCollection.contains(parent);
    if (firstTimeThrough) {
       AdapterViewCollection.add(parent);
     }
    return firstTimeThrough;
   }

Unterklasse ...

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
Jonathan Cole

Versuche dies

spinner.postDelayed(new Runnable() {
        @Override
        public void run() {
            addListeners();
        }
    }, 1000);.o
2

Sie können dies erreichen, indem Sie zunächst setOnTouchListener und dann setOnItemSelectedListener in onTouch festlegen

@Override
public boolean onTouch(final View view, final MotionEvent event) {
 view.setOnItemSelectedListener(this)
 return false;
}
1
vviieett

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

}

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

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
1
Ranjith Kumar

Um zu vermeiden, dass während der Initialisierung spinner.setOnItemSelectedListener () aufgerufen wird,

spinner.setSelection(Adapter.NO_SELECTION, true); //Add this line before setting listener
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {

    }
});
1
Ketan Ramani

Hatte das gleiche Problem und das funktioniert bei mir:

Ich habe 2 Spinner, und ich aktualisiere sie während der Initialisierung und während der Interaktionen mit anderen Steuerelementen oder nachdem ich Daten vom Server erhalten habe.

Hier ist meine Vorlage:

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) {

    }
}

Wenn die Klasse initiiert wird, verwenden Sie setSpinnersListeners () , anstatt den Listener direkt festzulegen.

Runnable verhindert, dass der Spinner direkt nach dem Einstellen der Werte aufItemSelected feuert.

Wenn Sie den Spinner (nach einem Serveraufruf usw.) aktualisieren müssen, verwenden Sie removeSpinnersListeners () direkt vor Ihren Updatezeilen und setSpinnersListeners () direkt nach den Updatezeilen. Dadurch wird verhindert, dass onItemSelected nach dem Update ausgelöst wird.

1
RoyBS

erstellen Sie ein boolesches Feld 

private boolean inispinner;

im Innern einer Aktivität

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (!inispinner) {
                inispinner = true;
                return;
            }
            //do your work here
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
    });
0