Android之增长的数字(仿支付宝资产数字)
16lz
2021-01-26
今天我们自定义一个TextView,它的名称叫做RiseNumberTextView,我们在平时使用支付宝的时候会发现进入资产页面的时候,资产数据会从一个数一直不停的增长直至你的真实数据然后停止。
那么这个效果是如何做到的呢?首先来看一下我们做出的效果图,然后我们一起来实现它。
这里面会用到一个核心的类:ValueAnimatr这是一个android属性动画
按照面向接口编程的好习惯,首先定义一个接口:
/** * 增长的数字接口 * */public interface IRiseNumber {/** * 开始播放动画的方法 */public void start();/** * 设置小数 * * @param number * @return */public void withNumber(float number);/** * 设置整数 * * @param number * @return */public void withNumber(int number);/** * 设置动画播放时长 * * @param duration * @return */public void setDuration(long duration);/** * 设置动画结束监听器 * * @param callback */public void setOnEndListener(RiseNumberTextView.EndListener callback);}
然后自定义view------数字增长TextView,内容如下:
import android.content.Context;import android.util.AttributeSet;import android.widget.TextView;import com.bear.risenumber.R;import com.nineoldandroids.animation.ValueAnimator;import java.text.DecimalFormat;/** * 自定义RiseNumberTextView继承TextView,并实现接口RiseNumberBase * */public class RiseNumberTextView extends TextView implements IRiseNumber {private static final int STOPPED = 0;private static final int RUNNING = 1;private int mPlayingState = STOPPED;private float number;private float fromNumber;/** * 动画播放时长 */private long duration = 1500;/** * 1.int 2.float */private int numberType = 2;private DecimalFormat fnum;private EndListener mEndListener = null;final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,99999999, 999999999, Integer.MAX_VALUE };/** * 构造方法 * * @param context */public RiseNumberTextView(Context context) {super(context);}/** * 使用xml布局文件默认的被调用的构造方法 * * @param context * @param attr */public RiseNumberTextView(Context context, AttributeSet attr) {super(context, attr);setTextColor(context.getResources().getColor(R.color.rise_number_text_color_red));setTextSize(30);}public RiseNumberTextView(Context context, AttributeSet attr, int defStyle) {super(context, attr, defStyle);}/** * 判断动画是否正在播放 * * @return */public boolean isRunning() {return (mPlayingState == RUNNING);}/** * 跑小数动画 */private void runFloat() {ValueAnimator valueAnimator = ValueAnimator.ofFloat(fromNumber, number);valueAnimator.setDuration(duration);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {setText(fnum.format(Float.parseFloat(valueAnimator.getAnimatedValue().toString())));if (valueAnimator.getAnimatedFraction() >= 1) {mPlayingState = STOPPED;if (mEndListener != null)mEndListener.onEndFinish();}}});valueAnimator.start();}/** * 跑整数动画 */private void runInt() {ValueAnimator valueAnimator = ValueAnimator.ofInt((int) fromNumber,(int) number);valueAnimator.setDuration(duration);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {//设置瞬时的数据值到界面上setText(valueAnimator.getAnimatedValue().toString());if (valueAnimator.getAnimatedFraction() >= 1) {//设置状态为停止mPlayingState = STOPPED;if (mEndListener != null)//通知监听器,动画结束事件mEndListener.onEndFinish();}}});valueAnimator.start();}static int sizeOfInt(int x) {for (int i = 0;; i++){if (x <= sizeTable[i])return i + 1;}}@Overrideprotected void onFinishInflate() {super.onFinishInflate();fnum = new DecimalFormat("##0.00");}/** * 开始播放动画 */@Overridepublic void start() {if (!isRunning()) {mPlayingState = RUNNING;if (numberType == 1)runInt();elserunFloat();}}/** * 设置一个小数进来 */@Overridepublic void withNumber(float number) {this.number = number;numberType = 2;if (number > 1000) {fromNumber = number- (float) Math.pow(10, sizeOfInt((int) number) - 1);} else {fromNumber = number / 2;}}/** * 设置一个整数进来 */@Overridepublic void withNumber(int number) {this.number = number;numberType = 1;if (number > 1000) {fromNumber = number- (float) Math.pow(10, sizeOfInt((int) number) - 2);} else {fromNumber = number / 2;}}/** * 设置动画播放时间 */@Overridepublic void setDuration(long duration) {this.duration = duration;}/** * 设置动画结束监听器 */@Overridepublic void setOnEndListener(EndListener callback) {mEndListener = callback;}/** * 定义动画结束接口 * * */public interface EndListener {/** * 当动画播放结束时的回调方法 */public void onEndFinish();}}
然后在Activity中去使用自定义的view:
import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.Toast;import com.bear.risenumber.views.RiseNumberTextView;import com.bear.risenumber.views.RiseNumberTextView.EndListener;public class MainActivity extends Activity {private RiseNumberTextView rnTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);setupViews();}private void setupViews() {// 获取到RiseNumberTextView对象rnTextView = (RiseNumberTextView) findViewById(R.id.risenumber_textview);// 设置数据rnTextView.withNumber(2666.50f);// 设置动画播放时间rnTextView.setDuration(5000);// 监听动画播放结束rnTextView.setOnEndListener(new EndListener() {@Overridepublic void onEndFinish() {Toast.makeText(MainActivity.this, "数据增长完毕...",Toast.LENGTH_SHORT).show();}});Button btn = (Button) findViewById(R.id.button1);btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if(rnTextView.isRunning()){Toast.makeText(MainActivity.this, "数字还没增长完,请稍候尝试...", Toast.LENGTH_SHORT).show();}else{// 开始播放动画rnTextView.start();}}});}}
附上示例源码,有兴趣的可以下载导入到Eclipse中去运行以下:
Android Rise Number TextView
更多相关文章
- 如何在5.0上实现button的Ripple(水波效果)
- Android(安卓)带清除功能的输入框控件EditTextWithDel
- Android(安卓)补间动画之平移动画TranslateAnimation
- 如何实现Android应用的启动画面(闪屏)?
- android viewPager滑动速度设置
- Android(安卓)Gradle配置资源前缀
- android 利用 MediaPlayer 类播放音乐
- Android(安卓)Activity process(进程设置)
- android imageview围绕中心旋转动画