Android spinner onItemSelected llamado varias veces después de la rotación de la pantalla
Tengo un diseño con tres hilanderos. Se diferencian en la opción presentada en la lista desplegable. En mi onCreateView
tengo un método para configurar los hilanderos. Dentro de ese método tengo algo como esto:
mySpinner = (Spinner) view.findViewById(R.id.my_spinner); ArrayAdapter<String> mySpinner = new ArrayAdapter<String>(getActivity(), R.layout.background, new ArrayList<String>(Arrays.asList(getResources().getStringArray(R.array.spinner_one_data)))); mySpinner.setDropDownViewResource(R.layout.spinner_text); mySpinner.setAdapter(mySpinner); mySpinner.setOnItemSelectedListener(this);
Como he dicho, mis otros dos hilanderos son casi el mismo, pero con diferentes opciones.
- Cambie el color de fondo del spinner pero mantenga la flecha
- Spinner: infla la excepción al usar AppCompat
- Android personalizado IcsSpinner (de ActionBarSherlock)
- Cómo personalizar un Spinner en Android
- Multi spinner de selección en android sin AlertDialog
Sé que onItemSelected
se llama una vez para cada hilandero en una "primera configuración" por lo que tengo una bandera para evitar este problema. Con esta solución bandera mis hiladoras están funcionando como se esperaba. El problema es cuando selecciono en cada hiladora una opción y luego roto la pantalla. Ahora, onItemSelected
se llama 6 veces en lugar de las 3 veces que estaba esperando (he establecido una bandera para gestionar esta situación de la llamada de 3 veces).
¿Por qué está sucediendo y azada debo manejar esto?
- Cómo agregar un elemento desplegable en la barra de acción
- NullPointerException con string-array en Spinner
- Establecer el color de fondo del elemento seleccionado en la navegación desplegable de Android
- Spinner no aplica el atributo dropDownSelector
- Cambiar Spinner dropdown icon
- el color de texto del hilandero es blanco?
- Personalización del espaciado de los hiladores
- Cómo mantener onItemSelected de disparar en un Spinner recién instanciado?
En general, he encontrado que hay muchos eventos diferentes que pueden desencadenar el método onItemSelected, y es difícil hacer un seguimiento de todos ellos. En su lugar, me resultó más sencillo utilizar un OnTouchListener para responder sólo a los cambios iniciados por el usuario.
Crear su oyente para el hilandero:
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 listener al spinner como OnItemSelectedListener y OnTouchListener:
SpinnerInteractionListener listener = new SpinnerInteractionListener(); mSpinnerView.setOnTouchListener(listener); mSpinnerView.setOnItemSelectedListener(listener);
He encontrado una solución que está funcionando para mí.
Tengo los 3
hiladores tan onItemSelected
se llama 3
veces en la disposición inicial del hilandero. Para evitar onItemSelected
de disparar un método en la configuración inicial he creado un contador para onItemSelected
sólo dispara el método en consecuencia el valor del contador.
Me he dado cuenta de que en mi situación, si una rotación de la pantalla, onItemSelected
se vuelve a encender las 3
veces, más un tiempo para cada spinner que no está en la posición 0
.
Un ejemplo:
Tengo los 3
hilanderos y el usuario cambia 2
de ellos a uno de la opción disponible, además de la posición 0
por lo que termina con una situación como esta:
First spinner - > Item 2 selected Second spinner -> Item 0 selected (no changes) Third spinner -> Item 1 selected
Ahora, cuando giro la pantalla, onItemSelected
será disparado 3
veces para la configuración del hilandero inicial más 2
veces para los hiladores que no están en la posición 0
.
@Override public void onSaveInstanceState(Bundle outState) { int changedSpinners = 0; if (spinner1.getSelectedItemPosition() != 0) { changedSpinners += 1; } if (spinner2.getSelectedItemPosition() != 0) { changedSpinners += 1; } if (spinner3.getSelectedItemPosition() != 0) { changedSpinners += 1; } outState.putInt("changedSpinners", changedSpinners); }
He guardado el estado en onSaveInstanceState
y, a continuación, en onCreateView
he comprobado si savedInstanceState != null
y si es así, extraído changedSpinners
del paquete y actualizado mi contador para actuar en consecuencia.