Cómo deshabilitar onItemSelectedListener que se invocará al configurar el elemento seleccionado por código

Sólo se pregunta cómo manejar el problema siguiente: un resultado se calcula en función de dos elementos seleccionados de hilanderos. Para manejar las cosas de la interfaz de usuario, es decir, un usuario escoge un elemento nuevo en una de las hiladoras, instalo un oyente utilizando setOnItemSelectedListener para la hiladora en mi método onCreate() de la actividad.

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

El problema: porque intercepto onPause() onResume() para guardar / restaurar el último estado, tengo un método que establece el elemento seleccionado por estos dos hilanderos de forma programática 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í!

Una aproximación directa estúpida para esto sería tener una variable booleana que inhabilite lo que el oyente hace dentro, fijándola antes de fijar los artículos seleccionados y de reajustarlo después. Bueno. ¿Pero hay un método mejor?

¡No quiero que los oyentes sean llamados por acciones de código, solo por las acciones del usuario! Unesdoc.unesco.org

¿Cómo lo haces? ¡Gracias!

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

Llamadas no deseadas onItemSelected

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

Crear su oyente para el hilandero como un 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 registro de hilandero para ambos tipos de evento

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

De esta manera, cualquier llamada inesperada a su método de controlador debido a la inicialización o reinicialización se ignorará.

Bueno, lo tengo funcionando de la manera que 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.

Lo que significa: a pesar de que establece los valores de Spinner aquí y allá: sólo se actualizan (visualmente) y sus oyentes sólo se llaman después de todos los métodos que están actualmente en (como onCreate , onResume o lo que sea) están terminados.

Esto permite lo siguiente:

  • Mantener las posiciones seleccionadas en las variables de campo. (Como currentPos1 , currentPos2 )
  • Los oyentes onItemSelectedListener() llaman a un método como refreshMyResult() o lo que sea.
  • Al establecer las posiciones de forma programática, establecer los hilanderos y llamar a su propio método de actualización manualmente después de eso.

El método refreshMyResult() tiene este aspecto:

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

Porque los oyentes serán llamados más tarde – y para entonces, la posición recordada en currentPos ya está actualizada – no pasará nada y ninguna actualización innecesaria de cualquier otra cosa tendrá lugar. Cuando un usuario selecciona un nuevo valor en uno de los hiladores, bien – la actualización se realizará en consecuencia!

¡Eso es! Todos los derechos reservados

Ahh – una cosa más: la respuesta a mi pregunta es: No. Los oyentes no pueden ser inhabilitados (fácilmente) y serán llamados cada vez que cambie un valor.

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

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

He creado una biblioteca que ayuda para todos, que no hay necesidad de llamar al elemento onClick acción en Spinner Por ejemplo:

 spinner.setSelection(withAction,position); 

Donde withAction es un indicador booleano, que se utiliza para la acción de llamada o no

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

Agregue OnItemSelectedListener para cada hilandero después de haber establecido cualquier valor anterior en onResume .

Cuando se utiliza Spinner.setSelection (posición), siempre activa setOnItemSelectedListener ()

Para evitar disparar el código dos veces utilizo 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és seguro de que Spinner.setSelection (position) us us. Además, es importante establecer mIsSpinnerFirstCall = true cada vez antes de usar Spinner.setSelection (posición)

  • Android Spinner Gravity No funciona
  • Spinner eliminar elementos
  • Spinner onItemSelected llamado erróneamente (sin acción del usuario)
  • Color del texto del cambio del androide de artículos en hilandero
  • SetOnItemSelectedListener de Spinner no llama
  • ¿Cómo puedo utilizar spinner setOnItemLongClickListener
  • Spinner se inicializa cuando empieza mi actividad - Android
  • Estoy tratando de crear un spinner dinámico
  • No se puede administrar a requestFocus a Spinner
  • ¿Ya no hay ningún indicador en el hilandero de Android 4.x?
  • Configuración del Adaptador del Spinner de Android en el hilador
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.