Contador de TextView de Android con animación Top / Down

Tenemos un TextView que me gustaría contar hacia abajo (9 … 3 … 2 … 1 … 0 o 0 … 1 … 3..6..9 cosas suceden).

Así (como cualquier medidor de tipo está trabajando):

Introduzca aquí la descripción de la imagen

Para que sea un poco más interesante, quiero que cada dígito vienen de arriba a abajo o de abajo a arriba?

Ahora mismo, usando listview para lograr esto, también he intentado con TextSwitcher pero su tiene una limitación de dos niños solamente.

Estoy usando getListView().smoothScrollToPosition(0...3...6...6...n) ;

¿Hay una manera simple de hacer esto? Porque ahora mismo, necesitamos mantener 3 ListView y Adapter también para mantener esto.

Por favor, consulte el enlace para entender esta pregunta.

Display StopWatch Timer animado como el medidor de gasolina con NSTimer

ListView 's podría ser la solución lo suficientemente buena, pero lo he implementado con una vista personalizada ( FrameLayout ), que contiene dentro de 2 TextView s, que están animando en función de los cambios de valor:

Introduzca aquí la descripción de la imagen

La idea del código es muy básica:

  • Se pasa al valor deseado setValue ;
  • Si es más grande que la animación actual de un inicio de abajo hacia arriba (y viceversa) para incrementar / disminuir el valor actual de 1. Aquí, TextView dos TextView a reemplazarlos;
  • En el oyente de AnimationEnd, compruebe si alcanzamos el valor deseado – si no – hacer una carrera más (recursivamente);

      public class DigitTextView extends FrameLayout { private static int ANIMATION_DURATION = 250; TextView currentTextView, nextTextView; public DigitTextView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public DigitTextView(Context context) { super(context); init(context); } private void init(Context context) { LayoutInflater.from(context).inflate(R.layout.digit_text_view, this); currentTextView = (TextView) getRootView().findViewById(R.id.currentTextView); nextTextView = (TextView) getRootView().findViewById(R.id.nextTextView); nextTextView.setTranslationY(getHeight()); setValue(0); } public void setValue(final int desiredValue) { if (currentTextView.getText() == null || currentTextView.getText().length() == 0) { currentTextView.setText(String.format(Locale.getDefault(), "%d", desiredValue)); } final int oldValue = Integer.parseInt(currentTextView.getText().toString()); if (oldValue > desiredValue) { nextTextView.setText(String.format(Locale.getDefault(), "%d", oldValue-1)); currentTextView.animate().translationY(-getHeight()).setDuration(ANIMATION_DURATION).start(); nextTextView.setTranslationY(nextTextView.getHeight()); nextTextView.animate().translationY(0).setDuration(ANIMATION_DURATION).setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { currentTextView.setText(String.format(Locale.getDefault(), "%d", oldValue - 1)); currentTextView.setTranslationY(0); if (oldValue - 1 != desiredValue) { setValue(desiredValue); } } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }).start(); } else if (oldValue < desiredValue) { nextTextView.setText(String.format(Locale.getDefault(), "%d", oldValue+1)); currentTextView.animate().translationY(getHeight()).setDuration(ANIMATION_DURATION).start(); nextTextView.setTranslationY(-nextTextView.getHeight()); nextTextView.animate().translationY(0).setDuration(ANIMATION_DURATION).setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {} @Override public void onAnimationEnd(Animator animation) { currentTextView.setText(String.format(Locale.getDefault(), "%d", oldValue + 1)); currentTextView.setTranslationY(0); if (oldValue + 1 != desiredValue) { setValue(desiredValue); } } @Override public void onAnimationCancel(Animator animation) {} @Override public void onAnimationRepeat(Animator animation) {} }).start(); } } } 

Y es XML:

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="48dp" android:layout_height="56dp" android:padding="8dp" android:background="@drawable/rounded_blue_rect"> <TextView android:id="@+id/currentTextView" android:textColor="#FFFFFF" android:textSize="18sp" android:gravity="center" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/nextTextView" android:textColor="#FFFFFF" android:textSize="18sp" android:layout_gravity="center" android:gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </FrameLayout> 

Y es muy fácil de usar:

Añadir al diseño:

 <klogi.com.myapplication.DigitTextView android:id="@+id/digitTextView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> 

Y establecer Valor en código:

 DigitTextView digitTextView = (DigitTextView) findViewById(R.id.digitTextView); digitTextView.setValue(5); 

Actualización:
Otra opción a utilizar, por lo que veo, es configurar un número personalizado NumberPicker

¡Espero que ayude!

Desde Robinhood ganó los premios de diseño de materiales que han abierto de origen allí TextView personalizado al igual que usted está describiendo.

Echa un vistazo a la biblioteca de Robinhood's Ticker

Introduzca aquí la descripción de la imagen

También puede utilizar un controlador para obtener el efecto deseado. Usando esto, no tendrá que hacer ninguna vista personalizada. Cree una función handleTextView que toma inicialValue , finalValue y targetTextview como argumentos. El método es-

 private void handleTextView(int initialValue, int finalValue, final TextView targetTextview) { DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(1f); final int newInitialValue = Math.min(initialValue, finalValue); final int newFinalValue = Math.max(initialValue, finalValue); final int difference = Math.abs(finalValue - initialValue); Handler handler = new Handler(); for (int count = newInitialValue; count <= newFinalValue; count++) { //Time to display the current value to the user. int time = Math.round(decelerateInterpolator.getInterpolation((((float) count) / difference)) * 100) * count; final int finalCount = ((initialValue > finalValue) ? initialValue - count : count); handler.postDelayed(new Runnable() { @Override public void run() { targetTextview.setText(finalCount.toString()); } }, time); } } 

UPDATE: Opción 2 – También puede utilizar un animador de valores –

 private void handleTextView(int initialValue, int finalValue, final TextView textview) { ValueAnimator valueAnimator = ValueAnimator.ofInt(initialValue, finalValue); valueAnimator.setDuration(1500); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { textview.setText(valueAnimator.getAnimatedValue().toString()); } }); valueAnimator.start(); } 

Usando este método no necesitamos hacer ninguna matemática.

  • Repetición de animaciones AnimatorSet varias veces
  • Cómo animar una vista con la animación de Google Translate en Android
  • Android animar mi diseño relativo de abajo hacia arriba y de arriba a abajo usando la animación de traducción en la vista de imagen haga clic
  • Animación de la vista de un niño fuera del padre
  • Animación RecyclerView no funciona
  • RecyclerView no se desplaza como se esperaba
  • Animaciones de propiedades vs Ver animaciones para el nuevo código de Android
  • ¿Cómo crear un diseño doblado personalizado con imageview y texto android?
  • Finaliza la actividad cuando se devuelve una respuesta del servidor, pero espera que termine la animación
  • Android L ViewAnimationUtils no encontrado?
  • Explosion animación de una vista en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.