转载请注明出处:http://blog.csdn.net/chay_chan/article/details/70196478

本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布

NumberRunningTextView介绍

  NumberRunningTextView是一个自带数字滚动动画的TextView,通过使用setContent(String str)方法,传入相应的金额数字字符串(如"1354.00"),或者数字的字符串(如200),当页面初始化完成的时候,就可以看到数字滚动的效果,和支付宝中进入余额宝界面,显示余额滚动的效果类似,具体的效果如下:

###使用
在布局文件中,使用NumberRunningTextView,代码如下:

演示金额滚动的NumberRunningTextView

 <com.chaychan.viewlib.NumberRunningTextViewandroid:id="@+id/tv_money"android:layout_width="wrap_content"android:layout_height="wrap_cointent"android:layout_centerInParent="true"android:text="0.00"android:textColor="#fff"android:textSize="30sp"android:textStyle="bold"/>

演示整数数字滚动的NumberRunningTextView

 <com.chaychan.viewlib.NumberRunningTextViewandroid:id="@+id/tv_num"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="200"android:textColor="#fff"android:textSize="30sp"app:textType="num"/>

  二者的区别在于textType的设置,textType是用于指定内容的格式,总共有money(金钱格式,带小数)和num(整数格式),默认是金钱的格式,不配置textType的话,默认就是使用金钱格式。

在java文件中根据id找到对应的view后,调用setContent()方法即可。

 tvMoney.setContent("1354.00");tvNum.setContent("200");

####关闭金额的自动格式化(每三位数字添加一个逗号)
  上图所示,最后显示的金额数字经过了处理,每三位添加一个逗号,这使得数字看起来比较好看,金额默认是使用这种格式,如果不想要这种格式的数字,可以在布局文件中,NumberRunningTextView的配置中,将useCommaFormat设置为false,这样最终的数字就不会是带有逗号了,效果如下:

####关闭执行动画的时机
  当一开始进入界面的时候,初始化数据完毕,NumberRunningTextView设置数据完毕,会自动执行数字滚动的动画,如果进行刷新操作,从服务器获取新的数据,重新设置数据,NumberRunningTextView会自动判断传入的内容是否有变化,如果没有变化,则不会再次滚动,这和支付宝的余额宝界面中的金额类似,当在余额宝界面下拉刷新时,金额没有变化,数字不会再次滚动,而当提现后重新回到该界面,金额发生变化后,就会再次滚动,效果如下:

SwipeRefreshLayout的刷新回调中,只做了这样的处理,NumberRunningTextView设置的内容还是原来的数据。

 srlRoot.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {tvMoney.setContent("1354.00");tvNum.setContent("200");srlRoot.setRefreshing(false);}});

  当你进行下拉刷新的时候,内容如果没有发生变化,数字是不会滚动的,如果内容发生变化,数字又会重新进行滚动,这里修改下拉刷新的代码,模拟数据变化的情况,演示一下:

 srlRoot.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {@Overridepublic void onRefresh() {tvMoney.setContent("1454.00");tvNum.setContent("300");srlRoot.setRefreshing(false);}});

效果如下:

  如果想要在刷新的时候,无论内容是否有变化都要执行滚动动画的话,可以在布局文件中,NumberRunningTextView的配置中,将runWhenChange设置为false即可,此时,无论内容是否有变化,都会执行滚动动画,效果如下:

修改帧数

  NumberRunningTextView默认是30帧,如果需要修改帧数,可以在布局文件中,NumberRunningTextView的配置中,将frameNum设置为自己想要的帧数。

NumberRunningTextView源码解析

  NumberRunningTextView的原理其实很简单,只是将一个数字除以帧数(默认是30帧),分成每段固定的大小进行递增。

首先介绍下NumberRunningTextView自定义的属性:

<declare-styleable name="NumberRunningTextView"><!--帧数--><attr name="frameNum" format="integer"></attr><!--内容的格式--><attr name="textType"><enum name="money" value="0"></enum><enum name="num" value="1"></enum></attr><!--是否使用每三位数字一个逗号--><attr name="useCommaFormat" format="boolean"></attr><!--是否当内容改变的时候使用动画,不改变则不使用动画--><attr name="runWhenChange" format="boolean"></attr></declare-styleable>

NumberRunningTextView继承于TextView

public class NumberRunningTextView extends TextView {public NumberRunningTextView(Context context) {this(context, null);}public NumberRunningTextView(Context context, AttributeSet attrs) {this(context, attrs, android.R.attr.textViewStyle);}public NumberRunningTextView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.NumberRunningTextView);frameNum = ta.getInt(R.styleable.NumberRunningTextView_frameNum, 30);textType = ta.getInt(R.styleable.NumberRunningTextView_textType, MONEY_TYPE);useCommaFormat = ta.getBoolean(R.styleable.NumberRunningTextView_useCommaFormat, true);runWhenChange = ta.getBoolean(R.styleable.NumberRunningTextView_runWhenChange,true);}...}

当调用setContent()方法时,里面做了相应的判断。

  /*** 设置需要滚动的金钱(必须为正数)或整数(必须为正数)的字符串** @param str*/
public void setContent(String str) {//如果是当内容改变的时候才执行滚动动画,判断内容是否有变化if (runWhenChange){if (TextUtils.isEmpty(preStr)){//如果上一次的str为空preStr = str;useAnimByType(str);return;}//如果上一次的str不为空,判断两次内容是否一致if (preStr.equals(str)){//如果两次内容一致,则不做处理return;}preStr = str;//如果两次内容不一致,记录最新的str}useAnimByType(str);
}

  如果runWhenChange为true,即当内容改变的时候才会滚动,进行如下判断,如果上次的内容为空(即第一次设置),则执行滚动,否则判断此次内容和上一次内容是否一致,如果一致,则不做处理,如果两次内容不一致,即内容发生了变化,记录当前的内容,并执行相应的滚动操作。

useAnimByType()方法只是用于判断内容的类型,并执行相应的动画,NumRunningTextView的核心为playMoneyAnim()和playNumAnim()

  private void useAnimByType(String str) {if (textType == MONEY_TYPE) {playMoneyAnim(str);} else {playNumAnim(str);}
}

下面对这两个方法进行解析:

/*** 播放金钱数字动画的方法** @param moneyStr*/
public void playMoneyAnim(String moneyStr) {String money = moneyStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号try {finalMoneyNum = Double.parseDouble(money);if (finalMoneyNum == 0) {//如果传入的为0,则直接使用setText()NumberRunningTextView.this.setText(moneyStr);return;}nowMoneyNum = 0;//记录每帧增加后的数字,一开始为0threadPool.execute(new Runnable() {@Overridepublic void run() {Message msg = handler.obtainMessage();double size = finalMoneyNum / frameNum;//数字除以帧数,得到每帧跳跃的大小msg.what = MONEY_TYPE;msg.obj = size < 0.01 ? 0.01 : size;// 如果每帧的间隔比0.01小,就设置为0.01handler.sendMessage(msg);// 发送通知改变UI}});} catch (NumberFormatException e) {e.printStackTrace();NumberRunningTextView.this.setText(moneyStr);//如果转换Double失败则直接用setText}
}

1.先对传入的字符串进行修改,如果有含有逗号或者负号,则去除逗号和负号;

2.对字符串进行格式转换,如果转换出现异常,则直接调用setText()方法设置内容;

3.如果传入的数字是0,则不用使用滚动动画,直接调用setText()设置内容;

4.如果传入的是正确的金额数字,将数字除以帧数frameNum,得到每一帧的大小(间隔),通过使用handler的sendMessage,传递当前内容的类型和每一帧数的大小,在Handler的handleMessage()方法中进行相应的处理。其中的threadPool为含有一个线程的线程池。threadPool = Executors.newFixedThreadPool(1);

Handler中的相应处理:

 private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case MONEY_TYPE://金钱数字的滚动String str = formatter.format(nowMoneyNum).toString();//保留两位小数的字符串// 更新显示的内容if (useCommaFormat) {//使用每三位数字一个逗号的格式String formatStr = StringUtils.addComma(str);//三位一个逗号格式的字符串NumberRunningTextView.this.setText(formatStr);} else {NumberRunningTextView.this.setText(str);}nowMoneyNum += (double) msg.obj;//记录当前每帧递增后的数字if (nowMoneyNum < finalMoneyNum) {//如果当前记录的金额数字小于目标金额数字,即还没达到目标金额数字,继续递增Message msg2 = handler.obtainMessage();msg2.what = MONEY_TYPE;msg2.obj = msg.obj;handler.sendMessage(msg2);// 继续发送通知改变UI} else {//已经达到目标的金额数字,显示最终的数字if (useCommaFormat) {NumberRunningTextView.this.setText(StringUtils.addComma(formatter.format(finalMoneyNum)));} else {NumberRunningTextView.this.setText(formatter.format(finalMoneyNum));}}break;case NUM_TYPE://普通数字滚动...break;}}
};

handleMessage()方法中,根据内容的类型进行相应的处理。

1.根据是否使用逗号进行格式化,显示每帧增加后的数字;

2.如果其小于finalMoneyNum目标数字(最终的数字),则继续调用sendMessage()方法,形成递归操作,直至等于或大于目标数字;

3.达到目标数字后,根据是否需要使用逗号进行格式化显示最终的效果

其中formatter = new DecimalFormat(“0.00”);// 格式化金额,保留两位小数,用于使double类型数字保留两位小数。

  到这里具体的设计思路应该都清楚了,其实就是通过使用handler不断发消息,形成递归,让数字进行递增,当达到最终的数字的时候,就停止发送消息,直接设置最终的内容。playNumAnim()也是一样的思路,在这里就不重复说明了,感觉自己的写的注释已经足够详细了,顺便贴一下playNumAnim()的方法。

/*** 播放数字动画的方法** @param numStr*/
public void playNumAnim(String numStr) {String num = numStr.replace(",", "").replace("-", "");//如果传入的数字已经是使用逗号格式化过的,或者含有符号,去除逗号和负号try {finalNum = Integer.parseInt(num);if (finalNum < frameNum) {//由于是整数,每次是递增1,所以如果传入的数字比帧数小,则直接使用setText()NumberRunningTextView.this.setText(numStr);return;}nowNum = 0;// 默认都是从0开始动画threadPool.execute(new Runnable() {@Overridepublic void run() {Message msg = handler.obtainMessage();int temp = finalNum / frameNum;//数字除以帧数,得到每帧跳跃的大小msg.what = NUM_TYPE;msg.obj = temp;handler.sendMessage(msg);// 发送通知改变UI}});} catch (NumberFormatException e) {e.printStackTrace();NumberRunningTextView.this.setText(numStr);//如果转换Double失败则直接用setText}
}

handler中对应的处理:

 private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case MONEY_TYPE://金钱数字的滚动...break;case NUM_TYPE://普通数字滚动NumberRunningTextView.this.setText(String.valueOf(nowNum));nowNum += (Integer) msg.obj;//记录当前每帧递增后的数字if (nowNum < finalNum) {//如果当前记录的数字小于目标数字,即还没达到目标数字,继续递增Message msg2 = handler.obtainMessage();msg2.what = NUM_TYPE;msg2.obj = msg.obj;handler.sendMessage(msg2);// 继续发送通知改变UI} else {//已经达到目标的数字,显示最终的内容NumberRunningTextView.this.setText(String.valueOf(finalNum));}break;}}
};

到这里为止,NumberRunningTextView的使用介绍和源码解析就结束了。下面介绍该控件的导入方式

导入方式

在项目根目录下的build.gradle中的allprojects{}中,添加jitpack仓库地址,如下:

allprojects {repositories {jcenter()maven { url 'https://jitpack.io' }//添加jitpack仓库地址}
}

打开app的module中的build.gradle,在dependencies{}中,添加依赖,如下:

dependencies {......compile 'com.github.chaychan:PowerfulViewLibrary:1.1.0'
}

源码github地址:https://github.com/chaychan/PowerfulViewLibrary.git

  依旧花了半天时间,完成了我的第四篇博客。上次写博客是在3月8号,其实一直想写多一点博客,但是一直觉得要么不写,要写就要写质量高的博客,虽然需要耗费许久的时间,因为我写文章都追求清晰明了,通俗易懂,不让读者觉得一头雾水,追求质量而不是数量。写博客也要有好的题材,想到哪个知识点比较让读者感兴趣和可以帮助到读者日常的开发,此次写这个NumberRunningTextView是在做项目的时候,在显示用户余额的时候,根据需求需要数字滚动的效果,所以就上网找了思路,自己写了这样一个View,觉得应该很多人都会需要用到,希望可以帮助到大家。

NumberRunningTextView(数字会滚动的TextView)相关推荐

  1. ShiftyTextview(数字会滚动的TextView)(仿支付宝余额显示,膜拜单车骑行数据显示)

    ShiftyTextview的介绍 ShiftyTextview是具有数字增加动画的 TextView ,通过 mShiftyTextview.setNumberString("99998. ...

  2. android自定义View-垂直滚动的TextView

    其实要让TextView能够滚动,可以使用ScrollView/HorizontalScrollView或者设置ScrollingMovementMethod来实现. 点击查看:android实现Te ...

  3. html数字自动滚动代码怎么写,你可能需要这样的大屏数字滚动效果

    大屏数字滚动效果来源于最近工作中一张大屏的UI图,该UI图上有一个模块需要有数字往上翻动的效果,以下是最终实现的效果: 思路 在实现此效果之前,我们先来捋一下思路,用思维导图来设计一下我们的实现步骤, ...

  4. Android怎么实现数字增减,Android实现数字跳动效果的TextView方法示例

    前言 本文介绍的是Android如何实现数字跳动效果的TextView,主要运用了DancingNumberView,DancingNumberView是一个用于跳动显示文本中数字的控件,继承自Tex ...

  5. vue 大屏数字上下滚动

    vue 大屏数字上下滚动 效果就是有数字变动时,会有一个动画跳到相应的数字,是上下滚动的那种. <div class="chartNum"><div class= ...

  6. 数码管显示数字(滚动和静态)

    数码管显示数字(滚动和静态) 1. 8只数码管滚动显示单个数字** 代码: #include<reg51.h> #include<intrins.h> #define uint ...

  7. Android-垂直上下滚动的TextView

    来自:https://github.com/paradoxie/AutoVerticalTextview 参考博客:Android-实现上下滚动的textview 相关类的继承关系: public c ...

  8. 原生js实现大屏数字上下滚动效果,支持随机多位数字

    一文看懂大屏数字滚动 前言 一.html 二.js生成展示的元素 三.css实现样式 四.加入动画和定时器 前言 在大屏项目中经常需要实现那种数字上下滚动的效果,普通的数字随机滚动在UI组件(例如Vi ...

  9. android开发游记:仿支付宝余额数字累加滚动效果的实现

    支付宝更新9.0后,细心的朋友会发现新增了一个动画效果,就是进入我的钱包的时候,我的余额会有一段滚动显示的动画效果,比如说你有100块,余额就从0滚动到100,看到自己的钱在不断涨,让我们这些穷屌丝莫 ...

最新文章

  1. spring boot中的日志入门
  2. 线上SQL脚本执行错了出事之后互相甩锅怎么办?
  3. homework-03
  4. python实现维吉尼亚加密法
  5. 为什么 MySQL 回滚事务也会导致 ibd 文件增大?
  6. 如果可以,我们一起留在竹山。
  7. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目8
  8. 初窥JQuery(一)-选择符 【转】
  9. python中0o10_Python基础10—I/O编程
  10. 关于IE6下用Jquery attr('onclick')问题
  11. 递归算法经典实例python-浅谈Python 递归算法指归
  12. Winsock API编程之UDP小结
  13. 帝国CMS系统标签e:loop调用的附加SQL条件和排序参数
  14. Scrapy学习路线
  15. 树莓派3B+ 人脸识别(OpenCV)
  16. winrar40天试用完了
  17. linux 下中文字体的支持
  18. 全套PR资源--含RAR解压密码
  19. 盛迈坤电商:自然流量怎么样打造爆款
  20. Ramdisk虚拟内存盘应该占多少物理内存?

热门文章

  1. JMeter 图片上传接口进行压力测试
  2. 程序设计入门——C语言 翁恺 第1周编程练习
  3. 安装matlab贝叶斯网络工具箱
  4. 选题难没思路?3招教你轻松建立小红书爆款选题库
  5. 关于Android模块化我有一些话不知当讲不当讲
  6. 获取当前位置的经度纬度
  7. 基于jsp的bbs论坛-(7)jsp网页的实现
  8. scratch四级考纲
  9. 河北单招计算机英语,2019年河北高职单招考试十类 和对口电子电工类、计算机类联考 专业基础考试(英语)考试大纲.doc...
  10. 那个跑外业的同事开始学习考测绘师了