• 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>

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

  • 相关阅读:
    美团前端面经-2020-估计是凉了
    JavaScript的垃圾回收机制与内存泄漏
    从输入URL到浏览器显示页面发生了哪些事情---个人理解
    let 、const 、var、function声明关键字的新理解
    前端中堆和栈的概念
    今天想好好的认真开始维护自己的博客
    关于org.apache.poi 导出excel时引发的No such file or directory
    MySQL查询本周、上周、本月、上个月份数据的sql代码
    为mybatis mapper xml文件添加注释遇到问题
    ubuntu使用中遇到问题及解决方法持续整理
  • 原文地址:https://www.cnblogs.com/dingxiansen/p/8658991.html
Copyright © 2020-2023  润新知