Cómo cambiar el valor de NumberPicker con animación?
He creado una aplicación para Android, en la que hay un NumberPicker. Y necesito cambiar el valor de este NumberPicker pero con una animación lisa como cuando usted lo toca y cambia su valor.
Por ejemplo, supongamos que el valor actual es 1 y va a ser 5, quiero que el NumberPicker gire de 1 a 2 y luego a 3 y así sucesivamente. Pero quiero que gire no sólo al instante cambiar los valores!
- Diálogo de PreferenciasActividad de Android con el selector de números
- Android Loading Selector de números personalizado Drawable
- Modificar el elemento seleccionado en Numberpicker Android
- Android NumberPicker, DatePicker, flechas TimePicker están desaparecidas
- NumberPicker no se muestra en AlertDialog
Si utilizo el código siguiente:
numberPicker.setValue(5);
Su valor cambiará instantáneamente a 5, pero quiero que ruede de 1 a 5 como cuando lo toque manualmente y lo haga girar.
- Configuración de typeFace a NumberPicker
- ¿Cómo obtener el número seleccionado de NumberPicker?
- Android NumberPicker envuelve valores cuando se cambian los valores mostrados
- ¿Cómo utilizar NumberPicker en la aplicación de Android con API 7?
- Cómo reducir el tamaño de fuente en NumberPicker
- Bloquear la transición entre el valor mínimo y el valor máximo en NumberPicker
- AlertDialog con NumberPicker procesado incorrectamente
- El valor predeterminado de Android Numberpicker no viene
Lo resolví vía refelction
/** * using reflection to change the value because * changeValueByOne is a private function and setValue * doesn't call the onValueChange listener. * * @param higherPicker * the higher picker * @param increment * the increment */ private void changeValueByOne(final NumberPicker higherPicker, final boolean increment) { Method method; try { // refelction call for // higherPicker.changeValueByOne(true); method = higherPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); method.setAccessible(true); method.invoke(higherPicker, increment); } catch (final NoSuchMethodException e) { e.printStackTrace(); } catch (final IllegalArgumentException e) { e.printStackTrace(); } catch (final IllegalAccessException e) { e.printStackTrace(); } catch (final InvocationTargetException e) { e.printStackTrace(); } }
Funciona perfecto. No sé por qué este método es privado
No creo que esto esté apoyado nativamente. Pensé en una forma "desordenada" de hacerlo manualmente:
Puede utilizar la función scrollBy (int x, int y) del NumberPicker llamada iterativamente para realizar el efecto de la animación.
Algunas cosas a tener en cuenta:
- ScrollBy (x, y) funciona con píxeles. Como Android tiene todas esas diferentes densidades de pantalla, lo que debes hacer es adivinar primero (lo haría por prueba y error) la distancia 'dp' que corresponde al desplazamiento a un valor consecutivo, y convertirlo a píxeles para Úsalo
- El primer parámetro de scrollBy (x, y) debe tomar un valor de 0, en caso de que no sea obvio
No he hecho animaciones yo mismo en Android, pero hay una API muy buena desde Honeycomb que probablemente hace que sea fácil de lograr esto.
Lo siento, pero este es el más fácil que podía pensar!
EDIT: Para convertir de 'dp' a pixeles:
private float pxFromDp(float dp) { return dp * this.getContext().getResources().getDisplayMetrics().density; }
Lo que tendrás que hacer es probar la llamada a scrollBy (0, pxFromDp (dp)) con diferentes valores 'dp', hasta que obtengas el exacto que mueve el NumberPicker hasta un número. Una vez que obtenga ese valor, puede crear su método de animación que al mover hacia arriba los números X desplazará X veces esta distancia dp.
Por favor, pregunte de nuevo si no lo entiende completamente 🙂
Gracias @passsy. Inspirado su respuesta: Esta solución admite múltiples pasos de incremento / decremento . Además, se puede ejecutar con un retardo de inicio y para varios númeroPickers (sin codificación adicional) .
class IncreaseValue { private int counter = 0; private final NumberPicker picker; private final int incrementValue; private final boolean increment; private final Handler handler = new Handler(); private final Runnable fire = new Runnable() { @Override public void run() { fire(); } }; /*public*/ IncreaseValue(final NumberPicker picker, final int incrementValue) { this.picker = picker; if (incrementValue > 0) { increment = true; this.incrementValue = incrementValue; } else { increment = false; this.incrementValue = -incrementValue; } } /*public*/ void run(final int startDelay) { handler.postDelayed(fire, startDelay); // This will execute the runnable passed to it (fire) // after [startDelay in milliseconds], ASYNCHRONOUSLY. } private void fire() { ++counter; if (counter > incrementValue) return; try { // refelction call for // picker.changeValueByOne(true); final Method method = picker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); method.setAccessible(true); method.invoke(picker, increment); } catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) { Log.d(TAG, "...", e); } handler.postDelayed(fire, 120); // This will execute the runnable passed to it (fire) // after 120 milliseconds, ASYNCHRONOUSLY. Customize this value if necessary. } }
El uso:
// Suppose picker1 as a NumberPicker IncreaseValue increasePicker1 = new IncreaseValue(picker1, 10); // So picker1 will be increased 10 steps. increasePicker1.run(0); // Increase immediately. If you want to run it from onCreate(), onStart() or ... of your activity, you will probably need to pass a positive value to it (eg 100 milliseconds).
Hay método privado dentro de NumberPicker, que es
changeCurrentByOne(boolean increment)
Puedes hacerlo público y usarlo. Puede ver este método en acción al presionar la flecha ARRIBA o ABAJO de NumberPicker. Probablemente no es lo que estás buscando, ya que este método no da mucho control de animación, pero es definitivamente mejor que setValue . Sin ninguna animación setValue parece terrible para el usuario.
- Android – ¿Cómo iniciar una aplicación de terceros con el nombre del paquete?
- Cómo publicar un mensaje en facebook friends wall en Android