Skip to content

Commit 2d5f358

Browse files
committed
TimeUtil 增加计算转换一个毫秒时间的方法convertATotalMillisTime2Hms
CountdownTextView 增加一个可倒计时的控件
1 parent 0fa530d commit 2d5f358

6 files changed

Lines changed: 415 additions & 0 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package common.base.utils;
2+
3+
import android.os.CountDownTimer;
4+
5+
/**
6+
* *****************(^_^)***********************<br>
7+
* User: fee(QQ/WeiXin:1176610771)<br>
8+
* Date: 2020/2/12<br>
9+
* Time: 15:24<br>
10+
* <P>DESC:
11+
* 倒数实现者
12+
* </p>
13+
* ******************(^_^)***********************
14+
*/
15+
public class CountdownTimerImpl extends CountDownTimer {
16+
/**
17+
* @param millisInFuture The number of millis in the future from the call
18+
* to {@link #start()} until the countdown is done and {@link #onFinish()}
19+
* is called.
20+
* @param countDownInterval The interval along the way to receive
21+
* {@link #onTick(long)} callbacks.
22+
*/
23+
public CountdownTimerImpl(long millisInFuture, long countDownInterval) {
24+
super(millisInFuture, countDownInterval);
25+
}
26+
27+
private ICountdown countdown;
28+
29+
public void setCountdown(ICountdown countdown) {
30+
this.countdown = countdown;
31+
}
32+
/**
33+
* Callback fired on regular interval.
34+
*
35+
* @param millisUntilFinished The amount of time until finished.
36+
*/
37+
@Override
38+
public void onTick(long millisUntilFinished) {
39+
if (countdown != null) {
40+
countdown.onTick(millisUntilFinished);
41+
}
42+
}
43+
44+
/**
45+
* Callback fired when the time is up.
46+
*/
47+
@Override
48+
public void onFinish() {
49+
if (countdown != null) {
50+
countdown.onFinish();
51+
}
52+
}
53+
54+
public interface ICountdown{
55+
void onFinish();
56+
57+
/**
58+
* 一次倒数回调
59+
* @param leftMillisUntilFinished 倒数后剩下的毫秒数
60+
*/
61+
void onTick(long leftMillisUntilFinished);
62+
}
63+
}

src/main/java/common/base/utils/TimeUtil.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,24 @@ public static String[] getTime2DDescInfos(String theGiveMillisTime,int descToday
268268
return twoDimensionDesc;
269269
}
270270
private static final String[] dayDesc = {"今天","昨天","前天","大前天"};
271+
272+
/**
273+
* 将一个毫秒时间转换成 时:分:秒
274+
* @param theMillisTime 毫秒时间
275+
* @return int[0] = 多少小时;int[1] = 多少分钟;int[2] = 多少秒。
276+
*/
277+
public static int[] convertATotalMillisTime2Hms(long theMillisTime) {
278+
int[] hmsInfos = new int[3];
279+
if (theMillisTime > 0) {//如果 <=0,则全是0
280+
int seconds = (int) (theMillisTime / 1000);//转换成总共有多少秒
281+
int minutes = seconds / 60;
282+
int hours = minutes / 60;
283+
minutes %= 60;
284+
seconds = seconds % 60;
285+
hmsInfos[0] = hours;
286+
hmsInfos[1] = minutes;
287+
hmsInfos[2] = seconds;
288+
}
289+
return hmsInfos;
290+
}
271291
}

src/main/java/common/base/utils/Util.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,4 +757,7 @@ public static String formatByteSize(long size,int sizeLevel) {
757757
BigDecimal result4 = new BigDecimal(teraBytes);
758758
return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
759759
}
760+
public static String formatStr(String formatStr, Object... params) {
761+
return String.format(Locale.getDefault(), formatStr, params);
762+
}
760763
}
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package common.base.views;
2+
3+
import android.content.Context;
4+
import android.graphics.Color;
5+
import android.support.annotation.ColorInt;
6+
import android.support.annotation.Nullable;
7+
import android.text.SpannableString;
8+
import android.util.AttributeSet;
9+
10+
import common.base.utils.CheckUtil;
11+
import common.base.utils.CommonLog;
12+
import common.base.utils.CountdownTimerImpl;
13+
import common.base.utils.TimeUtil;
14+
import common.base.utils.Util;
15+
16+
/**
17+
* *****************(^_^)***********************<br>
18+
* User: fee(QQ/WeiXin:1176610771)<br>
19+
* Date: 2020/2/12<br>
20+
* Time: 10:11<br>
21+
* <P>DESC:
22+
* 主动倒计时(按相应间隔时间递减)TextView
23+
* </p>
24+
* ******************(^_^)***********************
25+
*/
26+
public class CountdownTextView extends CustomTextView implements CountdownTimerImpl.ICountdown{
27+
private final String TAG = "CountdownTextView";
28+
private CountdownTimerImpl countDownTimer;
29+
30+
/**
31+
* 倒计时 前缀 文本
32+
* eg.: 剩余时间:
33+
*/
34+
private CharSequence countdownPrefixWords;
35+
36+
/**
37+
* 时、分、秒、背景颜色
38+
* 如果有的话,需要处理
39+
* def:0,透明,透明时不处理
40+
*/
41+
private @ColorInt int hourMinuteSecondBgColor;
42+
43+
/**
44+
* 时、分、秒、背景颜色 圆角的大小
45+
* def = 0;如果为0,则不使用圆角矩形背景
46+
*/
47+
private int bgColorSpanRadiusPxValue;
48+
/**
49+
* 时、分、秒、背景颜色 SPAN
50+
* 如果有的话,需要处理
51+
*/
52+
private RadiusCornerBackgroundColorSpan colorSpan4HourText;
53+
private RadiusCornerBackgroundColorSpan colorSpan4MinuteText;
54+
private RadiusCornerBackgroundColorSpan colorSpan4SecondText;
55+
/**
56+
* 总时间,单位:毫秒
57+
*/
58+
private long mMillisInFuture;
59+
60+
/**
61+
* The interval in millis that the user receives callbacks
62+
* 单位:毫秒
63+
* 倒数间隔:即以多长的时间间隔倒数一次,eg.: 1000(即以1秒的时间间隔倒数一次)
64+
*/
65+
private long mCountdownInterval;
66+
67+
protected boolean isDetachFromWindow = true;
68+
public CountdownTextView(Context context) {
69+
this(context,null);
70+
}
71+
72+
public CountdownTextView(Context context, @Nullable AttributeSet attrs) {
73+
super(context, attrs);
74+
//自定义属性
75+
76+
}
77+
78+
/**
79+
* 开始倒数
80+
* @param mMillisInFuture 总倒数的时间,单位:毫秒
81+
* @param mCountdownInterval 每次倒数时间间隔,单位:毫秒
82+
*/
83+
public void start(long mMillisInFuture, long mCountdownInterval) {
84+
boolean willRestart = false;
85+
if (mCountdownInterval <= 0 || mCountdownInterval > mMillisInFuture) {//该条件即包含了
86+
// mMillisInFuture <= 0了
87+
//这些个条件时,都不能执行任务
88+
if (countDownTimer != null) {
89+
countDownTimer.cancel();
90+
}
91+
onFinish();
92+
countDownTimer = null;
93+
return;
94+
}
95+
if (this.mMillisInFuture != mMillisInFuture || this.mCountdownInterval != mCountdownInterval) {
96+
willRestart = true;
97+
}
98+
this.mMillisInFuture = mMillisInFuture;
99+
this.mCountdownInterval = mCountdownInterval;
100+
if (willRestart) {
101+
if (countDownTimer != null) {
102+
countDownTimer.cancel();
103+
}
104+
countDownTimer = null;
105+
}
106+
if (countDownTimer == null) {
107+
countDownTimer = new CountdownTimerImpl(mMillisInFuture, mCountdownInterval);
108+
countDownTimer.setCountdown(this);
109+
onTick(mMillisInFuture);
110+
countDownTimer.start();
111+
}
112+
else {
113+
//如果不 为 null(可能时间参数一致的情况下),不需要 再start()
114+
}
115+
}
116+
117+
@Override
118+
protected void onDetachedFromWindow() {
119+
isDetachFromWindow = true;
120+
super.onDetachedFromWindow();
121+
log("onDetachedFromWindow()");
122+
}
123+
124+
@Override
125+
protected void onAttachedToWindow() {
126+
isDetachFromWindow = false;
127+
super.onAttachedToWindow();
128+
log("onAttachedToWindow()");
129+
}
130+
131+
/**
132+
* 倒数结束
133+
*/
134+
@Override
135+
public void onFinish() {
136+
log("onFinish()");
137+
showCountdownResultInfo(0);
138+
}
139+
140+
/**
141+
* 一次倒数回调
142+
* @param leftMillisUntilFinished 倒数后剩下的毫秒数
143+
*/
144+
@Override
145+
public void onTick(long leftMillisUntilFinished) {
146+
// log("onTick() leftMillisUntilFinished = " + leftMillisUntilFinished);
147+
if (isDetachFromWindow) {
148+
return;
149+
}
150+
showCountdownResultInfo(leftMillisUntilFinished);
151+
}
152+
153+
/**
154+
* 显示倒数一次后的信息
155+
* @param leftMillisUntilFinished 剩余的 时间,单位:毫秒
156+
*/
157+
protected void showCountdownResultInfo(long leftMillisUntilFinished) {
158+
// TODO: 2020/2/13 ???是否要交给外部来决定怎么显示
159+
int[] hms = TimeUtil.convertATotalMillisTime2Hms(leftMillisUntilFinished);
160+
//格式化时、分、秒
161+
String formatHmsStr = Util.formatStr("%02d:%02d:%02d", hms[0], hms[1], hms[2]);
162+
163+
String wholeShowText = formatHmsStr;
164+
if (!CheckUtil.isEmpty(countdownPrefixWords)) {
165+
wholeShowText = countdownPrefixWords + formatHmsStr;
166+
}
167+
if (hourMinuteSecondBgColor != 0) {
168+
//有背景颜色要处理
169+
int prefixWordsLen = 0;
170+
if (countdownPrefixWords != null) {
171+
prefixWordsLen = countdownPrefixWords.length();
172+
}
173+
int hourTextStartIndex = prefixWordsLen;
174+
int minuteTextStartIndex = hourTextStartIndex + 3;
175+
int secondTextStartIndex = minuteTextStartIndex + 3;
176+
SpannableString ss = new SpannableString(wholeShowText);
177+
ss.setSpan(colorSpan4HourText, hourTextStartIndex,
178+
hourTextStartIndex + 2,
179+
SpannableString.SPAN_INCLUSIVE_INCLUSIVE);
180+
181+
ss.setSpan(colorSpan4MinuteText, minuteTextStartIndex,
182+
minuteTextStartIndex + 2,
183+
SpannableString.SPAN_INCLUSIVE_INCLUSIVE);
184+
185+
ss.setSpan(colorSpan4SecondText, secondTextStartIndex,
186+
secondTextStartIndex + 2,
187+
SpannableString.SPAN_INCLUSIVE_INCLUSIVE);
188+
setText(ss);
189+
}
190+
else {
191+
setText(wholeShowText);
192+
}
193+
194+
}
195+
196+
private void log(String msg) {
197+
CommonLog.d(TAG, "---> " + msg);
198+
}
199+
200+
public CharSequence getCountdownPrefixWords() {
201+
return countdownPrefixWords;
202+
}
203+
204+
public void setCountdownPrefixWords(CharSequence countdownPrefixWords) {
205+
this.countdownPrefixWords = countdownPrefixWords;
206+
}
207+
208+
209+
public void setHourMinuteSecondBgColor(String hourMinuteSecondBgColor) {
210+
int theBgColor = 0;
211+
if (!CheckUtil.isEmpty(hourMinuteSecondBgColor)) {
212+
try {
213+
theBgColor = Color.parseColor(hourMinuteSecondBgColor);
214+
} catch (Exception ignore) {
215+
}
216+
}
217+
if (theBgColor != this.hourMinuteSecondBgColor) {
218+
this.hourMinuteSecondBgColor = theBgColor;
219+
buildColorSpans();
220+
}
221+
}
222+
223+
public void setHourMinuteSecondBgColor(@ColorInt int hourMinuteSecondBgColor) {
224+
if (this.hourMinuteSecondBgColor != hourMinuteSecondBgColor) {
225+
this.hourMinuteSecondBgColor = hourMinuteSecondBgColor;
226+
buildColorSpans();
227+
}
228+
}
229+
230+
public void setColorBgCornerRadius(int radius) {
231+
this.bgColorSpanRadiusPxValue = radius;
232+
}
233+
private void buildColorSpans() {
234+
if (this.hourMinuteSecondBgColor != 0) {
235+
colorSpan4HourText = new RadiusCornerBackgroundColorSpan(hourMinuteSecondBgColor,bgColorSpanRadiusPxValue);
236+
colorSpan4MinuteText = new RadiusCornerBackgroundColorSpan(hourMinuteSecondBgColor,bgColorSpanRadiusPxValue);
237+
colorSpan4SecondText = new RadiusCornerBackgroundColorSpan(hourMinuteSecondBgColor,bgColorSpanRadiusPxValue);
238+
}
239+
}
240+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package common.base.views;
2+
3+
import android.content.Context;
4+
import android.support.annotation.Nullable;
5+
import android.support.annotation.Px;
6+
import android.support.v7.widget.AppCompatTextView;
7+
import android.util.AttributeSet;
8+
import android.util.TypedValue;
9+
10+
/**
11+
* ******************(^_^)***********************<br>
12+
* User: fee(QQ/WeiXin:1176610771)<br>
13+
* Date: 2020/1/10<br>
14+
* Time: 11:35<br>
15+
* <P>DESC:
16+
* </p>
17+
* ******************(^_^)***********************
18+
*/
19+
public class CustomTextView extends AppCompatTextView {
20+
21+
public CustomTextView(Context context) {
22+
super(context);
23+
}
24+
25+
public CustomTextView(Context context, @Nullable AttributeSet attrs) {
26+
super(context, attrs);
27+
}
28+
29+
public CustomTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
30+
super(context, attrs, defStyleAttr);
31+
}
32+
33+
public void setTextSizeWithPxValue(@Px int textSizePxValue) {
34+
setTextSize(TypedValue.COMPLEX_UNIT_PX, textSizePxValue);
35+
}
36+
}

0 commit comments

Comments
 (0)