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>

主要的就是这三个文件,代码都全部贴出来了,效果也还可以。开发中不要重复造轮子,有的改一下就可以直接用咯。

原文地址:https://www.cnblogs.com/dingxiansen/p/8658991.html

时间: 2024-08-26 19:18:48

Android TextView数字增长动画效果的相关文章

android 仿ppt进入动画效果合集

EnterAnimation android 仿ppt进入动画效果合集, 百叶窗效果,擦除效果,盒状效果,阶梯效果,菱形效果,轮子效果,劈裂效果,棋盘效果, 切入效果,扇形展开效果,十字扩展效果,随机线条效果,向内溶解效果,圆形扩展效果, 适用于各种view和viewgroup,activity即用于页面根部viewgroup, 自定义viewgroup自动换行layout, 看效果图 Series of entrance animation effects just like ppt in A

Android 实现蘑菇街购物车动画效果

版本:1.0 日期:2014.8.6 版权:© 2014 kince 转载注明出处 使用过蘑菇街的用户基本上都知道有一个加入购物车的动画效果,此处不具体描述想知道的可以去下载体验一下. 1.思路 目前想到两种方式实现这种效果,一是使用Tween动画,直截了当的进行一个移动,蘑菇街就是使用这样的方法.二是使用WindowManager创建一个View,然后对这个View进行移动. 2.实现 本文先用方式一方法实现,之后会用方式二方法实现. 方式一: Activity代码: package com.

android中设置Animation 动画效果

在 Android 中, Animation 动画效果的实现可以通过两种方式进行实现,一种是 tweened animation 渐变动画,另一种是 frame by frame animation 画面转换动画,接下来eoe进行讲解. tweened animation 渐变动画有以下两种类型: 1.alpha   渐变透明度动画效果 2.scale   渐变尺寸伸缩动画效果 frame by frame animation 画面转换动画有以下两种类型: 1.translate  画面转换位置

Android Acitivy切换平移动画效果实现

1.在anim目录下新建anim文件夹,新建tran_in.xml和tran_out.xml分别表示下一页切换进入,和本页切换出去. 即in表示下一页向左平移,out表示同样向左平移至消失. tran_in.xml <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="100%p" X轴从100->0 android:toXDel

android AnimationDrawable类实现动画效果

布局文件xml <RelativeLayout 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:p

【转】Android 实现蘑菇街购物车动画效果

原文出处:http://blog.csdn.net/wangjinyu501/article/details/38400479 1.思路 目前想到两种方式实现这种效果,一是使用Tween动画,直截了当的进行一个移动,蘑菇街就是使用这样的方法.二是使用WindowManager创建一个View,然后对这个View进行移动. 2.实现 本文先用方式一方法实现,之后会用方式二方法实现. 方式一: Activity代码: 1 package com.kince.mogujie; 2 3 import a

教你如何实现 Android TextView 文字轮播效果

效果图: 实现思路: 1.ViewAnimator 思路 使用 ViewAnimator 自身特性,对期中的子 view 实现动画切换 2.自定义 viewGroup 思路 在这个思路下,我们自定义一个容器,继承 FrameLayout ,根据数据数量自己 new 相应数量的 itemView 出来加入 FrameLayout ,动画是通过对当前 itemView 做一个出去的佛纳甘话,同时对下一个 itemView 做一个进入动画,使用 handle 实现延迟轮换 3.ViewFlipper

android:TextView实现文字走马灯效果(欺骗系统获取持久的焦点)

通常情况下我们想实现文字的走马灯效果需要在xml文件中这样设置 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:singleLine="true" android:ellipsize="marquee" android:focusable="true" android:

android textview 实现跑马灯效果

跑马灯效果最重要的就是四个属性,分别是: android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:singleLine="true" 控件的宽度,不一定是具体的值,可以是math_parent,如果想让textview中的文字滚动的话,那里面内容的长度肯定是要大于控件的长度的,不然滚动还有啥