项目开发中,碰到了需要在apk启动进入程序时显示一个几秒中的广告图及注册或修改密码时需要获取验证码的效果,其实android系统已经封装了一个倒计时的类:CountDownTimer,可以很轻松的实现一个倒计时的效果。
效果如下:
代码实现如下:
/**
* 倒计时帮助类
*/
public class CountDownUtils {
// 倒计时timer
private CountDownTimer countDownTimer;
// 计时结束的回调接口
private OnFinishListener listener;
private Button button;
/**
* @param button 需要显示倒计时的Button
* @param defaultString 默认显示的字符串
* @param max 需要进行倒计时的最大值,单位是秒
* @param interval 倒计时的间隔,单位是秒
*/
public CountDownUtils(WeakReference<Button> weakReference,
final String defaultString, int max, int interval) {
if(weakReference==null){
return;
}
Button btn= weakReference.get();
if(btn==null){
return;
}
this.button = btn;
// 由于CountDownTimer并不是准确计时,在onTick方法调用的时候,time会有1-10ms左右的误差,这会导致最后一秒不会调用onTick()
// 因此,设置间隔的时候,默认减去了10ms,从而减去误差。
// 经过以上的微调,最后一秒的显示时间会由于10ms延迟的积累,导致显示时间比1s长max*10ms的时间,其他时间的显示正常,总时间正常
countDownTimer = new CountDownTimer(max * 1000, interval * 1000 - 10) {
@Override
public void onTick(long time) {
// 第一次调用会有1-10ms的误差,因此需要+15ms,防止第一个数不显示,第二个数显示2s
button.setText(defaultString + "(" + ((time + 15) / 1000)
+ "s)");
Log.d("CountDownUtils", "time = " + (time) + " text = "
+ ((time + 15) / 1000));
}
@Override
public void onFinish() {
button.setEnabled(true);
button.setText(defaultString);
if (listener != null) {
listener.finish();
}
}
};
}
/**
* 开始倒计时
*/
public void start(boolean isUser) {
if (isUser) {
button.setEnabled(true);
} else {
button.setEnabled(false);
}
countDownTimer.start();
}
/**
* 设置倒计时结束的监听器
*
* @param listener
*/
public void setOnFinishListener(OnFinishListener listener) {
this.listener = listener;
}
/**
* 计时结束的回调接口
*
* @author zhaokaiqiang
*/
public interface OnFinishListener {
void finish();
}
}
将CountDownTimer封装成一个工具类,在使用的时候调用传入相应的参数就可以了;
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.countdowntime.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:id="@+id/tel_layout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="手机号:"
android:textColor="#000000"
android:textSize="13sp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="15dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:hint="请输入手机号码"
android:textSize="13sp"
android:textColor="#000000"
android:inputType="number"/>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/tel_layout">
<TextView
android:id="@+id/tv_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="验证码:"
android:textColor="#000000"
android:textSize="13sp"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"/>
<EditText
android:layout_width="150dp"
android:layout_height="match_parent"
android:layout_marginLeft="15dp"
android:hint="请输入验证码"
android:textSize="13sp"
android:textColor="#000000"
android:inputType="number"
android:layout_toRightOf="@+id/tv_code"/>
<Button
android:id="@+id/btn_code"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取验证码"
android:textSize="11sp"
android:textColor="#000000"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:layout_centerVertical="true"
android:padding="8dp"
android:background="@drawable/code_button"
android:minHeight="0dp"
android:minWidth="0dp"/>
</RelativeLayout>
<ImageView
android:id="@+id/iv_ID"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@color/colorPrimary"
android:visibility="visible"/>
<Button
android:id="@+id/btn_ID"
android:layout_width="55dp"
android:layout_height="55dp"
android:background="@drawable/time_button"
android:textColor="#000000"
android:textSize="11sp"
android:text="跳过5秒"
android:layout_alignParentRight="true"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp"
android:visibility="visible"/>
</RelativeLayout>
上面这个是布局文件的代码,最终获取相应的控件,调用CountDownUtils工具类中相应的方法;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView ivTD;
private Button btnID;
private Button btnCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivTD= (ImageView) findViewById(R.id.iv_ID);
btnID= (Button) findViewById(R.id.btn_ID);
btnCode= (Button) findViewById(R.id.btn_code);
showID();
btnID.setOnClickListener(this);
btnCode.setOnClickListener(this);
}
/**
* 显示活动广告图
*/
private void showID(){
CountDownUtils countDown=new CountDownUtils(new WeakReference<Button>(btnID),"跳过", 5, 1);
//监听倒计时
countDown.setOnFinishListener(new CountDownUtils.OnFinishListener() {
@Override
public void finish() {
//显示完毕回调
//隐藏掉活动广告 和按钮
ivTD.setVisibility(View.GONE);
btnID.setVisibility(View.GONE);
}
});
//开启活动倒计时
countDown.start(true);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_ID:
jumpOver();
break;
case R.id.btn_code:
getCode();
break;
}
}
/**
* 点击了跳过
*/
private void jumpOver() {
//跳过点击
//隐藏掉活动广告 和按钮
ivTD.setVisibility(View.GONE);
btnID.setVisibility(View.GONE);
Toast.makeText(this,"点击了跳过",Toast.LENGTH_LONG).show();
}
/**
* 获取验证码
*/
private void getCode(){
CountDownUtils codeDown=new CountDownUtils(btnCode,"发送验证码", 60, 1);
//监听倒计时
codeDown.setOnFinishListener(new CountDownUtils.OnFinishListener() {
@Override
public void finish() {
}
});
//开启活动倒计时
codeDown.start(false);
Toast.makeText(this,"验证码已发送",Toast.LENGTH_LONG).show();
}
}
这样子效果就实现了,没错,就这么简单。