CountDownTimerUtil倒计时

CountDownTimerUtil倒计时

倒计时工具

倒计时(验证码倒计时、普通倒计时(包含结束显示内容、结束触发事件))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
* 倒计时(验证码倒计时、普通倒计时(包含结束显示内容、结束触发事件))
* Created by shenbh on 2017/8/22.
*/
public class CountDownTimerUtil extends CountDownTimer {

public static class CountDownBean {
private TextView mTextView;//倒计时控件
private long millisInFuture;//倒计时持续时间 The number of millis in the future from the call to {@link #start()} until the countdown is done and {@link #onFinish()} is called.
private long countDownInterval;//倒计时时间间隔 The interval along the way to receive {@link #onTick(long)} callbacks.

private SpannableStringBuilder textStyle;//文字格式
private String timeType;//倒计时时钟格式(如果要显示“60秒”样式,则直接传null)

private int countDownDrawableId = R.drawable.rectangle_darkblueedge_style;//倒计时时的背景
private int countDownTextColor = R.color.textgray;//倒计时时的文字的颜色

private String finishStr;//倒计时结束时显示的内容
private int finishDrawableId = R.drawable.rectangle_darkbluebg_style;//恢复时的背景
private int finishTextColor = R.color.white;//恢复时的文字的颜色
private OnFinishListener listener;//倒计时结束触发

public TextView getmTextView() {
return mTextView;
}

public void setmTextView(TextView mTextView) {
this.mTextView = mTextView;
}

public long getMillisInFuture() {
return millisInFuture;
}

public void setMillisInFuture(long millisInFuture) {
this.millisInFuture = millisInFuture;
}

public long getCountDownInterval() {
return countDownInterval;
}

public void setCountDownInterval(long countDownInterval) {
this.countDownInterval = countDownInterval;
}

public SpannableStringBuilder getTextStyle() {
return textStyle;
}

public void setTextStyle(SpannableStringBuilder textStyle) {
this.textStyle = textStyle;
}

public String getTimeType() {
return timeType;
}

public void setTimeType(String timeType) {
this.timeType = timeType;
}

public int getCountDownDrawableId() {
return countDownDrawableId;
}

public void setCountDownDrawableId(int countDownDrawableId) {
this.countDownDrawableId = countDownDrawableId;
}

public int getCountDownTextColor() {
return countDownTextColor;
}

public void setCountDownTextColor(int countDownTextColor) {
this.countDownTextColor = countDownTextColor;
}

public int getFinishDrawableId() {
return finishDrawableId;
}

public void setFinishDrawableId(int finishDrawableId) {
this.finishDrawableId = finishDrawableId;
}

public int getFinishTextColor() {
return finishTextColor;
}

public void setFinishTextColor(int finishTextColor) {
this.finishTextColor = finishTextColor;
}

public OnFinishListener getListener() {
return listener;
}

public void setListener(OnFinishListener listener) {
this.listener = listener;
}

public String getFinishStr() {
return finishStr;
}

public void setFinishStr(String finishStr) {
this.finishStr = finishStr;
}
}

private CountDownBean countDownBean;

/**
* @param countDownBean
*/
public CountDownTimerUtil(CountDownBean countDownBean) {
super(countDownBean.getMillisInFuture(), countDownBean.getCountDownInterval());
this.countDownBean = countDownBean;
}

@Override
public void onTick(long millisUntilFinished) {
countDownBean.getmTextView().setClickable(false);//设置不可点击

if (null != countDownBean.getTimeType()) {//传时间类型 比如timeType="mm:ss"
countDownBean.getmTextView().setText(TimeOrDateUtil.long2FormatTime(millisUntilFinished, countDownBean.getTimeType()));//long2FormatTime为long型转成timeType格式的String型
} else {

//适用60s验证码倒计时
countDownBean.getmTextView().setText(millisUntilFinished / 1000 + "秒"); //设置倒计时时间
countDownBean.getmTextView().setTextColor(MyApplication.getContext().getResources().getColor(countDownBean.getCountDownTextColor()));
countDownBean.getmTextView().setBackgroundResource(countDownBean.getCountDownDrawableId()); //倒计时背景色
countDownBean.getmTextView().setClickable(false);
countDownBean.getmTextView().setPadding(10, 5, 10, 5);

/**
* 超链接 URLSpan
* 文字背景颜色 BackgroundColorSpan
* 文字颜色 ForegroundColorSpan
* 字体大小 AbsoluteSizeSpan
* 粗体、斜体 StyleSpan
* 删除线 StrikethroughSpan
* 下划线 UnderlineSpan
* 图片 ImageSpan
* http://blog.csdn.net/ah200614435/article/details/7914459
*/
/*SpannableString spannableString = new SpannableString(countDownBean.getmTextView().getText().toString()); //获取按钮上的文字
ForegroundColorSpan span = new ForegroundColorSpan(Color.RED);*/
/**
* public void setSpan(Object what, int start, int end, int flags) {
* 主要是start跟end,start是起始位置,无论中英文,都算一个。
* 从0开始计算起。end是结束位置,所以处理的文字,包含开始位置,但不包含结束位置。
*/
/*spannableString.setSpan(span, 0, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);//将倒计时的时间设置为红色
countDownBean.getmTextView().setText(spannableString);*/
}
}

@Override
public void onFinish() {
countDownBean.getmTextView().setText(countDownBean.getFinishStr());
countDownBean.getmTextView().setClickable(true);//重新获得点击
countDownBean.getmTextView().setTextColor(MyApplication.getContext().getResources().getColor(countDownBean.getFinishTextColor()));
countDownBean.getmTextView().setBackgroundResource(countDownBean.getFinishDrawableId()); //还原背景色
countDownBean.getmTextView().setPadding(10, 5, 10, 5);
if (null != countDownBean.getListener()) {//写在倒计时结束的方法内,在倒计时结束的时候才会触发
countDownBean.getListener().onFinishListener();
}
}

/**
* 倒计时结束的时候触发事件
*/
public interface OnFinishListener {
void onFinishListener();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//TimeOrDataUtil.java

public static String YYYY_MM_DD = "yyyy-MM-dd";
public static String YYYY_MM_DD_HH_DD = "yyyy-MM-dd HH:mm";// 分钟
public static String YYYY_MM = "yyyy-MM";
public static String YYYY = "yyyy";
public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
public static String MM_SS = "mm:ss";

/**
* 传入long型返回对应格式的时间
*/
public static String long2FormatTime(long timeL,String type){
String formatTime="";
SimpleDateFormat sdf=new SimpleDateFormat(type);
Date dt=new Date(timeL);
formatTime=sdf.format(dt);
return formatTime;
}

上面的倒计时工具,用kotlin的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.CountDownTimer
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import android.widget.TextView
import com.ab.calculationtest.App
import com.ab.calculationtest.R
import java.text.SimpleDateFormat
import java.util.*

/**
* 倒计时(验证码倒计时、普通倒计时:包含结束显示内容、结束触发事件)
* @author shenbh
* time 2020/11/6 15:07
* 维护者
*/
class CountDownTimerUtil(private val countDownBean: CountDownBean) :
CountDownTimer(countDownBean.millisInFuture, countDownBean.countDownInterval) {

override fun onFinish() {
countDownBean.mTextView.text = countDownBean.finishStr
//重新获得点击
countDownBean.mTextView.isClickable = true
countDownBean.mTextView.setTextColor(App.context.resources.getColor(countDownBean.finishTextColor))
countDownBean.mTextView.setBackgroundColor(countDownBean.finishDrawableId)
countDownBean.mTextView.setPadding(10, 5, 10, 5)
countDownBean.listener.onFinishListener()
}

@SuppressLint("SetTextI18n")
override fun onTick(millisUntilFinished: Long) {
//设置不可点击
countDownBean.mTextView.isClickable = false

//传时间类型 比如timeType="mm:ss"
if (countDownBean.timeType != null) {
countDownBean.mTextView.text =
long2FormatTime(millisUntilFinished, countDownBean.timeType!!)
} else {
//适用60s验证码倒计时
countDownBean.mTextView.text = millisUntilFinished.div(1000).toString() + "秒"
countDownBean.mTextView.setTextColor(App.context.resources.getColor(countDownBean.countDownTextColor))
countDownBean.mTextView.setBackgroundColor(countDownBean.countDownDrawableId)
countDownBean.mTextView.isClickable = false
countDownBean.mTextView.setPadding(10, 5, 10, 5)

/**
* 超链接 URLSpan
* 文字背景颜色 BackgroundColorSpan
* 文字颜色 ForegroundColorSpan
* 字体大小 AbsoluteSizeSpan
* 粗体、斜体 StyleSpan
* 删除线 StrikethroughSpan
* 下划线 UnderlineSpan
* 图片 ImageSpan
* http://blog.csdn.net/ah200614435/article/details/7914459
*/
/*val spannableString = SpannableString(countDownBean.mTextView.text.toString())
//将倒计时的时间设置为红色
val span = ForegroundColorSpan(Color.RED)
//主要是start跟end,start是起始位置,无论中英文,都算一个。
//从0开始计算起。end是结束位置,所以处理的文字,包含开始位置,但不包含结束位置。
spannableString.setSpan(span, 0, 2, Spannable.SPAN_INCLUSIVE_EXCLUSIVE)
countDownBean.mTextView.setText(spannableString)*/
}
}

}

class CountDownBean {
//倒计时控件
lateinit var mTextView: TextView

//倒计时持续时间 The number of millis in the future from the call to {@link #start()} until the countdown is done and {@link #onFinish()} is called.
var millisInFuture: Long = 0

//倒计时时间间隔 The interval along the way to receive {@link #onTick(long)} callbacks.
var countDownInterval: Long = 0

//文字格式
lateinit var textStyle: SpannableStringBuilder

//倒计时时钟格式(如果要显示“60秒”样式,则直接传null)
var timeType: String? = null

//倒计时时的背景
var countDownDrawableId: Int = R.drawable.bg_circle_ff5252

//倒计时时的文字的颜色
var countDownTextColor: Int = android.R.color.white

//倒计时结束时显示的内容
lateinit var finishStr: String

//恢复时的背景
var finishDrawableId: Int = R.drawable.bg_circle_dddddd

//恢复时的文字的颜色
var finishTextColor: Int = android.R.color.darker_gray

//倒计时结束触发
lateinit var listener: OnFinishListener
}

interface OnFinishListener {
fun onFinishListener()
}

fun long2FormatTime(time: Long, type: String): String {
return SimpleDateFormat(type).format(Date(time))
}

调用

调用的地方:普通的传时间类型,触发结束事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void countDownTime(TextView tv) {
String finishStr = "重新发送";
WeakReference<CountDownTimerUtil.CountDownBean> wf = new WeakReference<CountDownTimerUtil.CountDownBean>(new CountDownTimerUtil.CountDownBean());
wf.get().setmTextView(tv);//倒计时控件
wf.get().setMillisInFuture(Constants.GETVERIFYCODE_MILLISINFUTURE);//倒计时持续时间 The number of millis in the future from the call to {@link #start()} until the countdown is done and {@link #onFinish()} is called.
wf.get().setCountDownInterval(1000);//倒计时时间间隔 The interval along the way to receive {@link #onTick(long)} callbacks.
wf.get().setTextStyle(StringUtil.setTextSizeColor(finishStr, Color.BLACK, 0, finishStr.length(), 14));//文字格式
wf.get().setTimeType(null);//倒计时时钟格式(如果要显示“60秒”样式,则直接传null)
wf.get().setFinishStr(finishStr);//倒计时结束时显示的内容

wf.get().setCountDownDrawableId(R.drawable.circle5_graybg_style);//倒计时时的背景
wf.get().setCountDownTextColor(R.color.white);//倒计时时的文字的颜色

wf.get().setFinishDrawableId(R.drawable.circle5_darkbluebg_style);//恢复时的背景
wf.get().setFinishTextColor(R.color.white);//恢复时的文字的颜色
//获取验证码倒计时
CountDownTimerUtil countDownTimerUtil = new CountDownTimerUtil(wf.get());
countDownTimerUtil.start();
}

Android 常用工具类之 Countdown

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import android.os.Handler;
import android.widget.TextView;

/**
* Created on 2021/4/2 11:58
* 倒计时器
*/
public class Countdown implements Runnable {
private int remainingSeconds;
private int currentRemainingSeconds;
private boolean running;
private String defaultText;
private String countdownText;
private TextView showTextView;
private Handler handler;
private CountdownListener countdownListener;
private TextViewGetListener textViewGetListener;

/**
* 创建一个倒计时器
* @param showTextView 显示倒计时的文本视图
* @param countdownText 倒计时中显示的内容,例如:"%s秒后重新获取验证码",在倒计时的过程中会用剩余描述替换%s
* @param remainingSeconds 倒计时秒数,例如:60,就是从60开始倒计时一直到0结束
*/
public Countdown(TextView showTextView, String countdownText, int remainingSeconds){
this.showTextView = showTextView;
this.countdownText = countdownText;
this.remainingSeconds = remainingSeconds;
this.handler = new Handler();
}

/**
* 创建一个倒计时器
* @param textViewGetListener 显示倒计时的文本视图获取监听器
* @param countdownText 倒计时中显示的内容,例如:"%s秒后重新获取验证码",在倒计时的过程中会用剩余描述替换%s
* @param remainingSeconds 倒计时秒数,例如:60,就是从60开始倒计时一直到0结束
*/
public Countdown(TextViewGetListener textViewGetListener, String countdownText, int remainingSeconds){
this.textViewGetListener = textViewGetListener;
this.countdownText = countdownText;
this.remainingSeconds = remainingSeconds;
this.handler = new Handler();
}

/**
* 创建一个倒计时器,默认60秒
* @param showTextView 显示倒计时的文本视图
* @param countdownText 倒计时中显示的内容,例如:"%s秒后重新获取验证码",在倒计时的过程中会用剩余描述替换%s
*/
public Countdown(TextView showTextView, String countdownText){
this(showTextView, countdownText, 60);
}

/**
* 创建一个倒计时器,默认60秒
* @param textViewGetListener 显示倒计时的文本视图获取监听器
* @param countdownText 倒计时中显示的内容,例如:"%s秒后重新获取验证码",在倒计时的过程中会用剩余描述替换%s
*/
public Countdown(TextViewGetListener textViewGetListener, String countdownText){
this(textViewGetListener, countdownText, 60);
}

private TextView getShowTextView(){
if(showTextView != null){
return showTextView;
}

if(textViewGetListener != null){
return textViewGetListener.OnGetShowTextView();
}

return null;
}

@Override
public void run() {
if(currentRemainingSeconds > 0){
getShowTextView().setEnabled(false);
getShowTextView().setText(
String.format(countdownText, currentRemainingSeconds));
if(countdownListener != null){
countdownListener.onUpdate(currentRemainingSeconds);
}
currentRemainingSeconds--;
handler.postDelayed(this, 1000);
}else{
stop();
}
}

public void start(){
defaultText = (String) getShowTextView().getText();
currentRemainingSeconds = remainingSeconds;
handler.removeCallbacks(this);
handler.post(this);
if(countdownListener != null){
countdownListener.onStart();
}
running = true;
}

public void stop(){
getShowTextView().setEnabled(true);
getShowTextView().setText(defaultText);
handler.removeCallbacks(this);
if(countdownListener != null){
countdownListener.onFinish();
}
running = false;
}

public boolean isRunning() {
return running;
}

public int getRemainingSeconds() {
return remainingSeconds;
}

public String getCountdownText() {
return countdownText;
}

public void setCountdownText(String countdownText) {
this.countdownText = countdownText;
}

public void setCurrentRemainingSeconds(int currentRemainingSeconds) {
this.currentRemainingSeconds = currentRemainingSeconds;
}

public void setCountdownListener(CountdownListener countdownListener) {
this.countdownListener = countdownListener;
}

/**
* 倒计时监听器
*/
public interface CountdownListener{
/**
* 当倒计时开始
*/
public void onStart();

/**
* 当倒计时结束
*/
public void onFinish();

/**
* 更新
* @param currentRemainingSeconds 剩余时间
*/
public void onUpdate(int currentRemainingSeconds);
}

public interface TextViewGetListener{
public TextView OnGetShowTextView();
}
}