studio onitemselected how example android listener spinner

android - how - Cómo deshabilitar onItemSelectedListener para que se invoque al configurar el elemento seleccionado por código



spinner layout android (11)

Primero agregue valores booleanos para detener la llamada del oyente del hilandero

Boolean check = false;

A continuación, agregue el oyente de toque y en el elemento haga clic en Listener Like below code

holder.filters.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { check = true; return false; } }); holder.filters.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View arg1, int position, long id) { flag = filterids.get(position); if(check) { check = false; new Applyfilters().execute(flag,"3"); }else{ } } @Override public void onNothingSelected(AdapterView<?> arg0) { // TODO Auto-generated method stub } });

Su simple trabajo es bueno para detener la llamada del servidor varias veces.

Solo me preguntaba cómo manejaría el siguiente problema: el resultado se calcula según los ítems seleccionados de dos rotativos. Para manejar las cosas de la interfaz de usuario, es decir, un usuario elige un nuevo elemento en uno de los giradores, instalo un oyente usando setOnItemSelectedListener para el spinner en mi método onCreate() de la actividad.

Ahora: eso funciona, por supuesto, bien. El trabajo del oyente es desencadenar un nuevo cálculo del resultado.

El problema: debido a que intercepto onPause() onResume() para guardar / restaurar el último estado, obtuve un método que establece el elemento seleccionado de estos dos rotuladores programáticamente como aquí:

startSpinner.setSelection(pStart); destSpinner.setSelection(pDest);

¡Estas dos llamadas invocan a los oyentes, también! ¡Mi método de cálculo para el resultado más la notificación de un nuevo conjunto de resultados se invoca dos veces aquí!

Un enfoque directo estúpido para esto sería tener una variable booleana que deshabilite lo que el oyente haga dentro, configurándola antes de configurar los elementos seleccionados y restableciéndola después. Bueno. ¿Pero hay un método mejor?

No quiero que los oyentes sean llamados por acciones de código, ¡solo por acciones de usuario! :-(

¿Cómo lo haces? ¡Gracias!


Agregue el OnItemSelectedListener para cada spinner después de haber establecido cualquier valor previo en onResume .


Creé una biblioteca que ayuda para todos, que no es necesario llamar al elemento en acción Hacer clic en Giro Por ejemplo:

spinner.setSelection(withAction,position);

donde withAction es una bandera booleana, que se usa para llamar o no a la acción de un elemento

Enlace en Github: https://github.com/scijoker/spinner2


Cuando se usa Spinner.setSelection (position), siempre activa setOnItemSelectedListener ()

Para evitar disparar el código dos veces, uso esta solución:

private mIsSpinnerFirstCall=true; ... Spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { //If a new value is selected (avoid activating on setSelection()) if(!mIsSpinnerFirstCall) { // Your code goes gere } mIsSpinnerFirstCall = false; } public void onNothingSelected(AdapterView<?> arg0) { } });

Esta solución es válida cuando está seguro de que Spinner.setSelection (position) us usó. Además, es importante establecer mIsSpinnerFirstCall = true cada vez antes de usar Spinner.setSelection (posición)


Es muy fácil llamar al método Spinner.setSelection(int position, boolean animate) con false para que los oyentes no reaccionen ante el cambio.


Está bien, lo tengo funcionando como quiero ahora.

Lo que hay que entender aquí (y no lo hice cuando estaba escribiendo esa pregunta ...) es que todo en Android se ejecuta en un hilo: el hilo de la interfaz de usuario.

Significado: aunque establezca los valores de Spinner aquí y allá: solo se actualizan (visualmente) y sus escuchas solo se onCreate onResume finalizan todos los métodos en los que se encuentra actualmente (como onCreate , onResume o lo que sea).

Esto permite lo siguiente:

  • mantener las posiciones seleccionadas en variables de campo. (como currentPos1 , currentPos2 )
  • los oyentes onItemSelectedListener() llaman a un método como refreshMyResult() o lo que sea.
  • cuando establezca las posiciones por programación, configure los giradores y llame a su propio método de actualización manualmente después de eso.

El método refreshMyResult() se ve así:

int newPos1 = mySpinner1.getSelectedItemPosition(); int newPos2 = mySpinner2.getSelectedItemPosition(); // only do something if update is not done yet if (newPos1 != currentPos1 || newPos2 != currentPos2) { currentPos1 = newPos1; currentPos2 = newPos2; // do whatever has to be done to update things! }

Debido a que se llamará a los oyentes más tarde, y para entonces, la posición recordada en currentPos ya está actualizada, no ocurrirá nada y no se realizará ninguna actualización innecesaria de nada más. Cuando un usuario selecciona un nuevo valor en uno de los giradores, bueno, ¡la actualización se realizará en consecuencia!

¡Eso es! :-)

Ahh, una cosa más: la respuesta a mi pregunta es: No. Los oyentes no pueden ser deshabilitados (fácilmente) y serán llamados cuando se cambie un valor.


Mi solución es muy fácil. Primero inicialice una variable booleana global.

boolean shouldWork = true;

Luego use el siguiente código en su método onCreate ().

Spinner spinner = findViewById(R.id.spinner); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapter, View v, int i, long lng) { if (shouldWork) { // Do your actions here } else shouldWork = true; } public void onNothingSelected(AdapterView<?> parentView) { } });

Ahora puede usar el método setSelection en everwhere sin invocar el método onItemSelected () por el código siguiente.

shouldWork = false; spinner.setSelection(0);


Spinner.setSelection (int position, boolean animate) activa el oyente en 4.3


Tengo una solución más fácil, y creo, mejor. Dado que tuve que actualizar los giradores incluso después de la inicialización, este es un enfoque más genérico. Por favor refiérase a la respuesta aceptada:

Llamadas no deseadas de elementos seleccionados


Una solución más limpia, en mi opinión, para diferenciar entre los cambios programáticos y los iniciados por el usuario es la siguiente:

Crea tu oyente para el girador como OnTouchListener y OnItemSelectedListener

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

Agregue el oyente al spinner registrándose para ambos tipos de eventos

SpinnerInteractionListener listener = new SpinnerInteractionListener(); mSpinnerView.setOnTouchListener(listener); mSpinnerView.setOnItemSelectedListener(listener);

De esta forma, se ignorarán todas las llamadas inesperadas a su método de controlador debido a la inicialización o reinicialización.


This following method will help you to stop invoking automatically the selection listener yourspinnerobj.post(new Runnable() { @Override public void run() { yourspinnerobj.setOnItemSelectedListener(yourspinnerlistener); } });