android最新实现获取验证码倒计时60s效果方法实践

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

最近做项目的过程中,在设计获取验证码按钮点击获取验证码倒计时的控件的时候,发现以前项目中用的做法太过于繁琐,本来是想直接将原来的代码拷贝过来使用的,但是后来还是在网上搜索了一番,于是乎有了今天的这篇博文,今天我将给大家介绍一下最新的处理倒计时逻辑的方法,那就是我们今天的主人公:CountDownTimer。

首先我们看看它引入的包是package android.os,说明这个类是安卓系统提供给我们使用的,并且[< Android API 24 Platform >] android.os,说明它是在安卓6.X版本推出的,难怪在以前的版本中没见到别人使用这个类呢。这个类很简单,点击进入查看源码发现其实代码很清晰明了,下面我们一起来看看,相信没什么难度,大家都能看懂:

public abstract class CountDownTimer {

    /**
     * Millis since epoch when alarm should stop.
     */
    private final long mMillisInFuture;

    /**
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;

    private long mStopTimeInFuture;

    /**
    * boolean representing if the timer was cancelled
    */
    private boolean mCancelled = false;

    /**
     * @param millisInFuture The number of millis in the future from the call
     *   to {@link #start()} until the countdown is done and {@link #onFinish()}
     *   is called.
     * @param countDownInterval The interval along the way to receive
     *   {@link #onTick(long)} callbacks.
     */
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }


    /**
     * Callback fired on regular interval.
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * Callback fired when the time is up.
     */
    public abstract void onFinish();


    private static final int MSG = 1;


    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else if (millisLeft < mCountdownInterval) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}
* 代码中最重要的几点,第一,是它的构造函数
public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

第一个参数millisInFuture是倒计时时长,比如说我们常用的60秒,那么这里就应该设置为60000毫秒,第二个参数countDownInterval是倒计时间隔,比如说我们的1秒钟为单位,那么这里就应该设置为1000毫秒。

* 代码中还有两个抽象方法:
/**
     * Callback fired on regular interval.
     * @param millisUntilFinished The amount of time until finished.
     */
    public abstract void onTick(long millisUntilFinished);

    /**
     * Callback fired when the time is up.
     */
    public abstract void onFinish();
  • 一个是onTick(long millisUntilFinished),这个就是倒计时中的回调方法,参数millisUntilFinished代表着还剩余的时间长度;
  • 另一个是onFinish(),这个就是倒计时结束的回调方法,当我们设置的60s时间倒计时完成了,我们就在这个方法里做我们的处理动作;

上面说了那么多,相信源码大家也能比较容易的看明白,那么结合我自己项目中的一个效果,我对这个控件做了一些封装,写个例子供大家参考,其实这些都很好实现。

  • 首先先创建一个drawable资源文件,点击按钮时背景有变化,命名为regist_suc.xml文件
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true">
         <shape>
             <corners android:radius="4dp"/>
             <solid android:color="#fff" />
             <stroke android:width="0.5dp" android:color="#179285"/>
         </shape>
     </item>

    <item>
        <shape>
            <corners android:radius="4dp"/>
            <solid android:color="#fff" />
            <stroke android:width="0.5dp" android:color="#1faa9b"/>
        </shape>
    </item>
</selector>
  • 创建一个类TimeCount,继承自CountDownTimer:
public class TimeCount extends CountDownTimer {
    private TextView tvCode;
    /**
     * @param millisInFuture    The number of millis in the future from the call
     *                          to {@link #start()} until the countdown is done and {@link #onFinish()}
     *                          is called.
     * @param countDownInterval The interval along the way to receive
     *                          {@link #onTick(long)} callbacks.
     */
    public TimeCount(long millisInFuture, long countDownInterval, TextView tv) {
        super(millisInFuture, countDownInterval);
        this.tvCode = tv;
    }

    @Override
    public void onTick(long millisUntilFinished) {
        tvCode.setBackgroundResource(R.drawable.regist_suc);
        tvCode.setTextSize(13);
        tvCode.setText(millisUntilFinished / 1000 +"秒");
        tvCode.setClickable(false);
    }

    @Override
    public void onFinish() {
        tvCode.setBackgroundResource(R.drawable.regist_suc);
        tvCode.setTextSize(13);
        tvCode.setText("再次接收");
        tvCode.setClickable(true);
    }

这里的构造函数中接收了一个TextView的控件,大家可以根据自己的需要修改。

  • 首页Activity的布局文件activity_main.xml文件也很简单:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/code"
        android:layout_width="60dp"
        android:layout_height="26dp"
        android:gravity="center"
        android:textColor="#00b097"
        android:textSize="16dp"
        android:layout_centerInParent="true"
        android:text="没收到?" />
</RelativeLayout>
  • 最后,在MainActivity中获取到TextView控件并且初始化TimeCount控件,代码清晰明了:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private TextView tvCode;
    private TimeCount time;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvCode = (TextView) findViewById(R.id.code);
        tvCode.setOnClickListener(this);
        time = new TimeCount(60000,1000,tvCode);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.code:
                time.start();
                //在这里请求获取验证码的接口即可
                break;
        }
    }
}

下面是运行时的几张截图,最终效果:
这里写图片描述
这里写图片描述
这里写图片描述


如果你觉得我的文章对你有帮助,并且希望帮助更多人,欢迎分享并关注我的微信公众号“Android开发的奥秘”,或扫描识别下方的二维码,我会不定期的分享给大家更多有用的资讯,谢谢!
这里写图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胖子爱你520

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值