443 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/

8voto

fusion44 Punkte 312

Nachdem ich mir lange Zeit die Haare gerauft habe, habe ich nun meine eigene Spinner-Klasse entwickelt. Ich habe ihr eine Methode hinzugefügt, die die Verbindung zum Hörer entsprechend trennt und herstellt.

public class SaneSpinner extends Spinner {
    public SaneSpinner(Context context) {
        super(context);
    }

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

    public SaneSpinner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    // set the ceaseFireOnItemClickEvent argument to true to avoid firing an event
    public void setSelection(int position, boolean animate, boolean ceaseFireOnItemClickEvent) {
        OnItemSelectedListener l = getOnItemSelectedListener();
        if (ceaseFireOnItemClickEvent) {
            setOnItemSelectedListener(null);
        }

        super.setSelection(position, animate);

        if (ceaseFireOnItemClickEvent) {
            setOnItemSelectedListener(l);
        }
    }
}

Verwenden Sie es in Ihrem XML wie folgt:

<my.package.name.SaneSpinner
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/mySaneSpinner"
    android:entries="@array/supportedCurrenciesFullName"
    android:layout_weight="2" />

Alles, was Sie tun müssen, ist die Instanz von SaneSpinner nach dem Aufblasen abzurufen und die Auswahl wie folgt zu setzen:

mMySaneSpinner.setSelection(1, true, true);

Dadurch wird kein Ereignis ausgelöst und die Benutzerinteraktion wird nicht unterbrochen. Dies hat die Komplexität meines Codes erheblich reduziert. Dies sollte in Stock Android enthalten sein, da es wirklich eine PITA ist.

1 Stimmen

Das funktioniert bei mir nicht, es löst immer noch onItemSelected aus.

0 Stimmen

Arthez überprüfe bitte, ob du wirklich true an das dritte Argument übergibst. Wenn ja, ist hier etwas anderes falsch. Wenn möglich, poste deinen Code.

8voto

redocoder Punkte 201

Keine unerwünschten Ereignisse aus der Layout-Phase, wenn Sie das Hinzufügen des Listeners verschieben, bis das Layout fertig ist:

spinner.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ensure you call it only once works for JELLY_BEAN and later
            spinner.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            // add the listener
            spinner.setOnItemSelectedListener(new OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                    // check if pos has changed
                    // then do your work
                }

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

            });

        }
    });

0 Stimmen

Das funktioniert, und es ist IMO die sauberste Lösung für das spezifische Problem des Auftraggebers. Ich möchte anmerken, dass Sie die ViewTreeObserver.OnGlobalLayoutListener bei Versionen unter J durch Aufruf von ViewTreeObserver.removeGlobalOnLayoutListener die veraltet ist und einen ähnlichen Namen wie die in dieser Antwort verwendete Methode hat.

6voto

Jeslin Jacob Punkte 212

Ich habe eine sehr einfache Antwort bekommen, die zu 100 % sicher ist, dass es funktioniert:

boolean Touched=false; // this a a global variable

public void changetouchvalue()
{
   Touched=true;
}

// this code is written just before onItemSelectedListener

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

//inside your spinner.SetonItemSelectedListener , you have a function named OnItemSelected iside that function write the following code

if(Touched)
{
 // the code u want to do in touch event
}

3voto

SagiLow Punkte 5321

Da nichts für mich gearbeitet, und ich habe mehr als 1 Spinner in meiner Ansicht (und IMHO halten eine bool-Map ist ein Overkill) Ich verwende das Tag, um die Klicks zu zählen:

spinner.setTag(0);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Integer selections = (Integer) parent.getTag();
            if (selections > 0) {
                // real selection
            }
            parent.setTag(++selections); // (or even just '1')
        }

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

3voto

g00dy Punkte 6742

Ich habe dafür eine viel elegantere Lösung gefunden. Sie beinhaltet das Zählen, wie oft der ArrayAdapter (in Ihrem Fall "Adapter") aufgerufen wurde. Sagen wir, Sie haben 1 Spinner und Sie rufen:

int iCountAdapterCalls = 0;

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

Deklarieren Sie einen int-Zähler nach dem onCreate und setzen Sie dann innerhalb der onItemSelected()-Methode eine "if"-Bedingung, um zu prüfen, wie oft der Adapter aufgerufen wurde. In Ihrem Fall haben Sie es nur einmal so aufgerufen:

if(iCountAdapterCalls < 1)
{
  iCountAdapterCalls++;
  //This section executes in onCreate, during the initialization
}
else
{
  //This section corresponds to user clicks, after the initialization
}

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