Android TextView数字增长动画效果
某些app上,新进入一个Activity的时候,上面的一个关键性数字(比如金额)会以一个数字不断变大的动画来显示。刚开始的时候,想到的一个方案是:使用Thead+Handler,给定一个动画总时长与刷新间隔时长,根据公式(数字从0开始,每次增长值为数组除以动画执行次数,动画执行次数等于动画总时长除以刷新间隔时长);
每隔一段时间重新设置TextView的字符串为增加后的值,直到动画结束显示最终结果。
其实对安卓动画有一定了解的应该都知道ValueAnimator这个类,我们可以使用它来很好的实现所要的效果,而不需要我们自己来生硬的控制隔多久就增加多少刷新显示。根据ValueAnimator的属性方法以及实际需要,我们封装一个自定义View来实现我们的需求。
先看一下我实现的效果图
接下来上关键代码:
自定义View,其实就是继承一个TextView,代码实现很简单,代码中也有注释
/** * Created by dingchao on 2018/3/27. */ public class DcTextViewRunNumber extends TextView { /** * 延迟 */ private final int DELAY = 20; /** * 保留小数位数 默认2为 */ private final int DECIMALS_COUNT = 2; private final int START_RUN = 101; private final int STOP_RUN = 102; /** * 跑的次数 */ private final int RUN_COUNT = 40; private float speed; private float startNum; private float endNum; /** * 保留小数位数 */ private int decimals = DECIMALS_COUNT; /** * 每次跑的次数 */ private int runCount = RUN_COUNT; /** * 动画延迟 */ private int delayMillis = DELAY; private boolean isAniming; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == START_RUN) { if(speed==0){ if(endNum!=0){ speed = getSpeed(); startNum = speed; }else{ return ; } } isAniming = !running(); if (isAniming) { sendEmptyMessageDelayed(START_RUN, delayMillis); }else{ speed = 0; startNum = 0; } } }; }; public DcTextViewRunNumber(Context context) { super(context); } public DcTextViewRunNumber(Context context, AttributeSet attrs) { super(context, attrs); } public DcTextViewRunNumber(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * 开始数字跳动动画 * @return 动画是否结束 */ private boolean running() { setText(withDEC(String.valueOf(startNum)) + ""); startNum +=speed; if(startNum >= endNum){ setText(withDEC(String.valueOf(endNum)) + ""); return true; } return false; } /** * 计算速度 * @return */ private float getSpeed(){ float speedFloat = withDEC(String.valueOf(endNum/runCount)).floatValue(); return speedFloat; } /** * 判断是否是非负数 * @return */ private boolean isNumber(String num){ if("".equals(num) || num==null) return false; Pattern pattern = Pattern.compile("^\\d+$|\\d+\\.\\d+$"); Matcher matcher = pattern.matcher(num); return matcher.find(); } /** * 取整四舍五入 保留小数 * @param num * @return */ private BigDecimal withDEC(String num){ return new BigDecimal(num).setScale(decimals, BigDecimal.ROUND_HALF_UP); } /** * 设置显示的数字 * @param num */ public void setShowNum(String num){ setShowNum(num,DECIMALS_COUNT); } /** * 设置显示的数字 * @param num * @param decimals 要保留的小数位 */ public void setShowNum(String num,int decimals){ if(!isNumber(num)){ return; } setText(num); setDecimals(decimals); } /** * 开始跑 */ public void startRun(){ if(isAniming){ return ; } if(isNumber(getText().toString())){ endNum = withDEC(getText().toString()).floatValue(); mHandler.sendEmptyMessage(START_RUN); } } public int getDecimals() { return decimals; } /** * 设置保留的小数位 0:不保留小数 * @param decimals */ public void setDecimals(int decimals) { if(decimals>=0){ this.decimals = decimals; } setText(withDEC(getText().toString())+""); } public int getRunCount() { return runCount; } /** * 设置动画跑的次数 * @param runCount */ public void setRunCount(int runCount) { if(runCount<=0){ return ; } this.runCount = runCount; } public int getDelayMillis() { return delayMillis; } /** * 设置动画延迟 * @param delayMillis */ public void setDelayMillis(int delayMillis) { this.delayMillis = delayMillis; }
接下来看怎么使用,MainActivity.java中
public class MainActivity extends AppCompatActivity { private DcTextViewRunNumber numberRunView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); numberRunView = (DcTextViewRunNumber) findViewById(R.id.numberRunView); numberRunView.setShowNum("711", 0);//终止的数字,小数点,这里为0所以没有小数点 numberRunView.setRunCount(50);//动画执行的次数,50次执行完 // numberRunView.setShowNum("221.918899"); numberRunView.startRun();// } /** * @param view */ public void runClick(View view) { numberRunView.startRun(); } }
activity_main.xml也贴一下吧,贴全了吧
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <cn.up.com.textviewrun.DcTextViewRunNumber android:id="@+id/numberRunView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="123" android:textSize="30sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:onClick="runClick" android:text="跑" /> </LinearLayout>
主要的就是这三个文件,代码都全部贴出来了,效果也还可以。开发中不要重复造轮子,有的改一下就可以直接用咯。