项目中经常会遇到找回密码的功能,现在找回密码一般都是用手机接收验证码,为了防止多次发送,一般需要设置一个发送间隔,比如60秒。为了让用户更加清楚的感受到这个间隔,于是就出现了倒计时功能.如下图:
点击之后,获取验证码的那个TextView或者Button变为不可点击,并且它的的text就要每秒变化一次,59,58,57…到最后一秒之后,text重新变为点击获取验证码,而且变为可点击.
看了一些前辈写的倒计时,都是用Handler和TimerTask来实现,然后我发现了一个更加简单的,Android自带的类来写这个功能.
接下来我就以一个简单的例子来实现这个功能。
1、activity_main.XML,为一个Button即可.
<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”
>
<Button
android:textSize=”25dp”
android:id=”@+id/btn_get”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”
android:text=”点击获取验证码” />
</RelativeLayout>
2、MainActivity.java,既为重头戏,又极为简单.
package com.example.rr;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
private Button mButton;//定义一个Button
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton=(Button) findViewById(R.id.btn_get);//←←获取按钮ID
//设置监听↓↓
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
mButton.setClickable(false);
mButton.setTextColor(Color.parseColor(“#FF0000″));
MyTimer myTimer=new MyTimer(5000, 1000);//定义MyTimer的对象
myTimer.start();//启动倒计时
}});
}
private class MyTimer extends CountDownTimer{
//millisInFuture为你设置的此次倒计时的总时长,比如60秒就设置为60000
//countDownInterval为你设置的时间间隔,比如一般为1秒,根据需要自定义。
public MyTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
// TODO Auto-generated constructor stub
}@Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
mButton.setText(millisUntilFinished/1000+”秒后重新获取”);
}
//每过你规定的时间间隔做的操作↑↑
//倒计时结束时做的操作↓↓
@Override
public void onFinish() {
// TODO Auto-generated method stub
mButton.setClickable(true);
mButton.setTextColor(Color.parseColor(“#000000”));
mButton.setText(“点击获取验证码”);
}}}
在各个关键点我也做了标注,下面是我给大家录的gif.
timer
大家可以发现有2个问题:
1、在1秒的时候,会停顿大约两秒,这样就给了用户不太好的体验,还以为是手机卡了.为什么会出现这种问题呢?
2、点击Button时,出现的是数字4而不是数字5。
首先我们得知道这种方法的原理是什么,大家先看一下CountDownTimer的源码:
首先大家看一下这句: mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
再看下下面的这句: final long millisLeft = mStopTimeInFuture – SystemClock.elapsedRealtime();
(注意:SystemClock.elapsedRealtime()返回的是系统运行到现在的时间,每时每刻都在变化);
如果简单的进行数学计算的话,那么一开始mStopTimeInFuture是等于millisLeft的,但是不然,SystemClock.elapsedRealtime()返回的时间,以毫秒为单位,也就是说,从上面运行到下面,也消耗了些许时间,那么millisLeft就是小于5000的。
回到我们的Activity,我们在内部类的OnTick里写了什么?
mButton.setText(millisUntilFinished/1000+”秒后重新获取”);那么4900多除以1000后,返回的数值为4。
解决方案:
在我们实例化MyTimer时,将5000改为6000.
至于在1秒处停顿的情况,我们看一下最下面的if else 语句:
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);
在 else if 语句处,当millisLeft<mCountdownInterval=1000,时,只进行停顿,而不调用OnTick方法,也就是说,我们运行程序时,millisLeft的数值从4900多~3900~2900~1900~900,900的时候,运行到这里,就会停顿,而不显示我们在OnTick写的代码.
解决方案:
重写CountDownTimer类。
然后,
1、在else if 中加OnTick(millisLeft);
2、删掉这个if else 语句
OK,我在重写类之后,将if else 语句改为下面的时候,依旧可以完成倒计时功能:
if (millisLeft <= 0) {
onFinish();
} else {
onTick(millisLeft);
sendMessageDelayed(obtainMessage(MSG), 1000);
}
效果gif如下:
是不是写这个类的大牛想复杂了,还是我这个方法有问题呢?有知道的道友可以联系我~万分感谢!
PS:写这个文章浪费了快一下午,原因是网速不好,快写完了,保存草稿,然后出现意外,导致没保存,所以,,,,但是还是希望得到各位的建议和鼓励,谢谢!