2016-01-29 6 views
7

Wir haben einen TextView, den ich gerne runterzählen würde (9 ... 3 ... 2 ... 1 ... 0 oder 0 ... 1 ... 3..6..9 Sachen passiert).Android TextView Zähler mit Top/Down Animation

Like this (Wie jeder Art Meter arbeitet):

enter image description here

Um es ein wenig interessanter zu machen, ich will nach oben jede Stelle kommen von oben nach unten oder von unten?

Momentan benutze ich listview um dies zu erreichen, habe ich auch mit TextSwitcher versucht, aber es hat eine Begrenzung von nur zwei Kindern.

Ich benutze getListView().smoothScrollToPosition(0...3...6...6...n);

Gibt es eine einfache Möglichkeit, dies zu tun? denn gerade jetzt müssen wir 3 ListView und Adapter auch für die Aufrechterhaltung dieser beibehalten.

Siehe Link zu mehr verstehen diese Frage

Display StopWatch Timer animated like the petrol pump meter using NSTimer

+1

Mit 3 'ListView's ist keine gute Idee. Vielleicht ist es besser 3 TextViews zu verwenden (eins für jede Ziffer) und sie dann abhängig vom Zählerwert zu animieren. – Rami

+0

Ja, ich dachte auch das Gleiche, aber ich habe verschiedene Probleme während der Animation bemerkt, –

Antwort

28

ListView ist vielleicht gut genug Lösung sein, aber ich habe es mit einer benutzerdefinierten Ansicht implementiert (FrameLayout), die innerhalb 2 TextView s enthält , die auf den Wertänderungen basieren Animieren:

enter image description here

Die Idee des Code ist sehr einfach:

  • Sie gehen zu setValue gewünschten Wert;
  • Wenn es größer als der aktuelle ist - starten Sie die Animation von unten nach oben (und umgekehrt), um den aktuellen Wert um 1 zu erhöhen/verringern. Hier animieren wir zwei TextView s, um einander zu ersetzen;
  • Überprüfen Sie im AnimationEnd-Listener, ob wir den gewünschten Wert erreicht haben - falls nicht - führen Sie einen weiteren (rekursiv) aus;

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

Und es ist 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> 

Und es ist sehr einfach zu bedienen:

zu Layout hinzufügen:

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

und Sollwert in Code:

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

Upd:
Eine weitere Option zu verwenden, von dem, was ich sehe, ein wenig einzurichten angepasst ist NumberPicker

Ich hoffe, es hilft!

1

Sie können auch einen Handler verwenden, um den gewünschten Effekt zu erzielen. Dadurch müssen Sie keine benutzerdefinierten Ansichten erstellen.Erstellen eine Funktion handleTextView, die in Anfangswert nimmt, Endwert und targetTextview als Argumente. Das Verfahren ist

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: Option 2- Sie Wert Animator als gut

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(); 

} 

Durch die Verwendung dieser Methode können wir brauchen keine Mathematik zu tun.

4

Seit Robinhood die Material Design Awards gewonnen hat, haben sie Open Source dort benutzerdefinierte TextView genau wie Sie beschreiben.

Check out Robinhood's Ticker Bibliothek

enter image description here