We want a Meter animation in TextView
To make it a little more interesting, I want each digit come from top to bottom or bottom to top ?
Right now I using listview for achieving this, I have also tried with TextSwitcher
but its have a limitation of two child only.
I'm using getListView().smoothScrollToPosition(0...3...6...6...n)
;
Is there a simple way of doing this? because right now , we need to maintain 3 ListView
and Adapter
as well for maintaining this.
Please refer link to more understand this question
Display StopWatch Timer animated like the petrol pump meter using NSTimer
ListView
's might be good enough solution, but I've implemented it with a custom View (FrameLayout
), which contains inside 2 TextView
s, which are animating based on the value changes:
The idea of code is very basic:
setValue
desired value;TextView
s to replace each other; In AnimationEnd listener, check if we reached desired value - if not - do one more run (recursively);
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();
}
}
}
And it's 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>
And it's very easy to use:
Add to layout:
<klogi.com.myapplication.DigitTextView
android:id="@+id/digitTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
And set Value in code:
DigitTextView digitTextView = (DigitTextView) findViewById(R.id.digitTextView);
digitTextView.setValue(5);
Upd:
Another option to use, from what I see, is to set up a bit customized NumberPicker
I hope, it helps!
Ever since Robinhood won the Material design awards they have open sourced there custom TextView
just like you are describing.
Check out Robinhood's Ticker library
This code performs the same animation where number rolldown from top to bottom.
Rolling-TextView-Animation
You can also use a handler to get the desired effect. Using this, you won't have to make any custom views. Create a function handleTextView which takes in initialValue, finalValue and targetTextview as arguments. The method is-
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- You can use a value animator as well-
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();
}
By using this method we do not need to do any math.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With