Android Spinner: unikaj połączeń onItemSelected podczas inicjalizacji

Stworzyłem aplikację na Androida z Spinner i TextView. Moim zadaniem jest wyświetlenie wybranego elementu z rozwijanej listy w widoku tekstowym. Zaimplementowałem Spinner w metodzie onCreate, więc kiedy uruchamiam program, pokazuje on wartość w TextView (przed wybraniem elementu z rozwijanej listy).

Chcę pokazać wartość w widoku tekstowym dopiero po wybraniu elementu z rozwijanej listy. Jak to zrobić?

Oto Mój kod:

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

    }
}
Author: Pratik Butani, 2012-11-15

11 answers

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

Więc pierwszy raz obsłużyć to z dowolną liczbą całkowitą

Przykład: Początkowo Wziąć 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);
   }
}

Możesz to zrobić z wartością logiczną, a także sprawdzając bieżące i poprzednie pozycje. zobacz tutaj

 127
Author: Abhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:23

Just put this line before set OnItemSelectedListener

spinner.setSelection(0,false)

Podanie false jako drugiego parametru powoduje ustawienie zaznaczenia bez animowania zmiany. Animacja spowoduje opóźnienie w ustawianiu wartości, co może prowadzić do nieoczekiwanych wyników. Mianowicie, ustawienie słuchacza po ustawieniu wartości początkowej spowoduje, że słuchacz pozycji otrzyma selekcję, nawet jeśli selekcja jest ustawiona przed ustawieniem słuchacza.

 53
Author: Dayanand Waghmare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-27 19:57:39

Począwszy od poziomu API 3, możesz użyć onuserinteraction () na aktywności z logiką, aby określić, czy użytkownik wchodzi w interakcję z urządzeniem.

Http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()

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

Jako pole działania, które mam:

 private boolean userIsInteracting;
W końcu mój 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) {

           }
      });

Gdy przechodzisz przez aktywność, wartość logiczna jest resetowana do wartości false. Działa jak urok.

 45
Author: Bill Mote,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 23:42:09

To zadziałało dla mnie

Inicjalizacja spinnera w Androidzie jest czasami problematyczna powyższy problem został rozwiązany przez ten wzór.

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

Ustawienie adaptera powinno być pierwszą częścią, a onItemSelectedListener (this) będzie ostatnią podczas inicjalizacji spinnera. Przez wzorzec powyżej moje onitemselected () nie jest wywoływane podczas inicjalizacji spinner

 11
Author: saksham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-23 07:53:30

Haha...Mam to samo pytanie. Kiedy initviews () po prostu robi tak.Sekwencja jest kluczem, słuchacz jest ostatnim. Powodzenia !

spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
 10
Author: Treesouth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-14 01:26:38

Moje rozwiązanie:

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
Author: codareee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-23 15:32:24

Możesz to zrobić w ten sposób:

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

        }
    });

Na początku tworzę słuchacza i przypisuję do zmiennej callback; następnie tworzę drugiego słuchacza anonimowego i kiedy to zostanie wywołane po raz pierwszy, zmienia to słuchacza =]

 5
Author: Charleston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-11 02:30:05

Podobne proste rozwiązanie, które umożliwia wielokrotne obracanie jest umieszczenie AdapterView w kolekcji-w Activities superclass - przy pierwszym wykonaniu onItemSelected(...) Następnie sprawdź, czy AdapterView znajduje się w kolekcji przed jej wykonaniem. Umożliwia to jeden zestaw metod w superklasie i obsługuje wiele adapterów i do nich wiele spinnerów.

Superklasa ...

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

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

Podklasa ...

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
Author: Jonathan Cole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-18 22:25:26

Miałem ten sam problem i to mi działa:

Mam 2 Spinnery i aktualizuję je podczas init oraz podczas interakcji z innymi kontrolkami lub po pobraniu danych z serwera.

Oto mój szablon:

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

    }
}

Gdy Klasa inicjuje użycie setSpinnersListeners() zamiast ustawiania bezpośrednio słuchacza.

Runnable zapobiegnie odpalaniu wirnika onitemselected zaraz po ustawieniu ich wartości.

Jeśli chcesz zaktualizować spinner (po wywołaniu serwera itp.) użyj removeSpinnersListeners () tuż przed liniami aktualizacji i setSpinnersListeners () tuż po liniach aktualizacji. Uniemożliwi to uruchomienie onItemSelected po aktualizacji.

 1
Author: RoyBS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-22 15:04:33

Flaga interakcji użytkownika może być ustawiona na true w metodzie onTouch i zresetowana w onItemSelected() po przetworzeniu zmiany wyboru. Preferuję To rozwiązanie, ponieważ flaga interakcji użytkownika jest obsługiwana wyłącznie dla spinnera, a nie dla innych widoków w aktywności, które mogą mieć wpływ na pożądane zachowanie.

W kodzie:

Stwórz słuchacza dla spinnera:

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
        }
    }

}

Dodaj słuchacz do spinnera zarówno jako OnItemSelectedListener, jak i OnTouchListener:

SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
 1
Author: Ranjith Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-07 03:39:59

Można to osiągnąć przez setOnTouchListener najpierw następnie setOnItemSelectedListener w onTouch

@Override
public boolean onTouch(final View view, final MotionEvent event) {
 view.setOnItemSelectedListener(this)
 return false;
}
 0
Author: vviieett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 08:06:11