Android TextView счетчик с верхней / вниз анимации
у нас есть TextView, который я хотел бы отсчитать (9...3...2...1...0 или 0...1...3..6..9 всякое бывает).
как это(как любой вид метр работает):
чтобы сделать его немного более интересным, я хочу, чтобы каждая цифра иди сверху вниз или снизу вверх ?
прямо сейчас я использую listview для достижения этого, я также пробовал с TextSwitcher
но у него есть ограничение в два ребенка только.
Я использую getListView().smoothScrollToPosition(0...3...6...6...n)
;
есть ли простой способ сделать это? потому что прямо сейчас нам нужно поддерживать 3 ListView
и Adapter
а также для поддержания этого.
пожалуйста, обратитесь по ссылке, чтобы больше понять этот вопрос
дисплей секундомер таймер анимированные, как бензиновый насос метр с помощью NSTimer
3 ответов
ListView
может быть достаточно хорошим решением, но я реализовал его с пользовательским представлением (FrameLayout
), который содержит внутри 2 TextView
s, которые анимируются на основе изменений значений:
идея кода очень проста:
- передать в
setValue
нужное значение; - если он больше, чем текущий один - начать анимацию снизу вверх (и наоборот), чтобы увеличить / уменьшить текущее значение к 1. Здесь мы оживляем двух
TextView
s, чтобы заменить друг друга; -
в прослушивателе AnimationEnd проверьте, достигли ли мы желаемого значения-если нет-выполните еще один запуск (рекурсивно);
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(); } } }
и это 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>
и это очень простой в использовании:
добавить в макет:
<klogi.com.myapplication.DigitTextView
android:id="@+id/digitTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
и установите значение в коде:
DigitTextView digitTextView = (DigitTextView) findViewById(R.id.digitTextView);
digitTextView.setValue(5);
Upd:
Другой вариант использования, из того, что я вижу, - это настроить немного настроить NumberPicker
Я надеюсь, это поможет!
С тех пор, как Robinhood выиграл премию Material design awards, они открыли там пользовательскиеTextView
Так же, как вы описываете.
проверить Робингуд-х библиотека
вы также можете использовать обработчик для получения желаемого эффекта. Используя это, вам не придется создавать пользовательские представления. Создайте функцию handleTextView которая принимает initialValue, finalValue и targetTextview в качестве аргументов. Метод-
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);
}
}
обновление: Вариант 2 - вы также можете использовать аниматор значений -
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();
}
используя этот метод, нам не нужно делать математику.