這次帶來一個倒計時控件,命名爲TimingTextView,依然是隻有一個文件,複製粘貼即可用。話不多說,上本體:
TimingTextView.java:
public class TimingTextView extends TextView {
private static final int TIME_START = 0x001;
private static final int TIME_FINISH = 0x002;
private static final int TIME_CHANGE = 0x003;
private static final int TIME_RESET = 0x004;
private static final int TIMING = 0x005;
// 中文模式,顯示格式爲 00小時00分00秒
public static final int CHINESE = 0x101;
// 數字模式,顯示格式爲 00:00:00
public static final int MATH = 0x102;
// 顯示精確到小時
public static final int HOUR = 0x201;
// 顯示精確到分
public static final int MINUTE = 0x202;
// 顯示精確到秒
public static final int SECOND = 0x203;
// 當前顯示格式
private int languageMode = MATH;
// 當前精確位數
private int timeMode = HOUR;
// 倒計時模式下的最大時間
private int maxTime = 60;
// 當前時間
private int time;
// 是否倒計時模式
private boolean isCountDown = true;
// 是否自動刷新顯示
private boolean isAutoRefresh = true;
private TimingThread thread;
private boolean isTiming;
private boolean isPausing;
// 計時回調
private OnTimingListener listener;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
try {
switch (msg.what) {
case TIME_CHANGE:
setText(calculateTime(time));
break;
case TIME_START:
if (listener != null) listener.onStart();
break;
case TIME_RESET:
setText(calculateTime(time));
stop();
break;
case TIME_FINISH:
if (listener != null) listener.onFinish();
break;
case TIMING:
if (listener != null) {
listener.onTiming(((time / (60 * 60) + "").length() == 1 ? "0" : "") + time / (60 * 60),
((time % (60 * 60) / 60 + "").length() == 1 ? "0" : "") + time % (60 * 60) / 60,
((time % 60 + "").length() == 1 ? "0" : "") + time % 60, TimingTextView.this);
}
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
public TimingTextView(Context context) {
this(context, null);
}
public TimingTextView(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
public TimingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setText(calculateTime(maxTime));
}
/**
* 計算顯示的時間
*
* @param time 當前時間
* @return 時間字串
*/
private String calculateTime(int time) {
String hour = ((time / (60 * 60) + "").length() == 1 ? "0" : "") + time / (60 * 60);
String minute = ((time % (60 * 60) / 60 + "").length() == 1 ? "0" : "") + time % (60 * 60) / 60;
String second = ((time % 60 + "").length() == 1 ? "0" : "") + time % 60;
return (timeMode == HOUR ? hour : "") + (timeMode == HOUR ? languageMode == CHINESE ? "小時" : ":" : "")
+ (timeMode == HOUR || timeMode == MINUTE ? minute : "") + (timeMode == HOUR || timeMode == MINUTE ? languageMode == CHINESE ? "分" : ":" : "")
+ second + (languageMode == CHINESE ? "秒" : "");
}
private void sendMessage(int what, Handler handler) {
Message message = new Message();
message.what = what;
handler.sendMessage(message);
}
/**
* 開始計時
*/
public void start() {
if (!isTiming) {
thread = new TimingThread();
thread.start();
}
}
/**
* 暫停計時
*/
public void pause() {
isPausing = true;
}
/**
* 繼續計時
*/
public void resume() {
isPausing = false;
}
/**
* 停止計時
*/
public void stop() {
isTiming = false;
isPausing = false;
}
/**
* 時間重置
*/
public void reset() {
time = isCountDown ? maxTime : 0;
isTiming = true;
isPausing = false;
sendMessage(TIME_RESET, handler);
}
/**
* 設置顯示格式
*
* @param languageMode 模式,可選項:CHINESE、MATH
*/
public void setLanguageMode(int languageMode) {
this.languageMode = languageMode;
setText(calculateTime(isCountDown ? maxTime : 0));
}
/**
* 設置顯示精確位數
*
* @param timeMode 精確位數,可選項:HOUR、MINUTE、SECOND
*/
public void setTimeMode(int timeMode) {
this.timeMode = timeMode;
setText(calculateTime(isCountDown ? maxTime : 0));
}
/**
* 最大計時時間,只在倒計時模式下有效
*
* @param maxTime 最大時間,單位秒
*/
public void setMaxTime(int maxTime) {
this.maxTime = maxTime;
setText(calculateTime(isCountDown ? maxTime : 0));
}
/**
* 設置是否倒計時
* 設置爲false時從零開始往上計時,無計時上限
*
* @param isCountDown
*/
public void setIsCountDown(boolean isCountDown) {
this.isCountDown = isCountDown;
setText(calculateTime(isCountDown ? maxTime : 0));
}
/**
* 是否自動刷新顯示
* 設置爲false時需要在回調接口裏手動更新需要顯示的文字
*
* @param isAutoRefresh
*/
public void setIsAutoRefresh(boolean isAutoRefresh) {
this.isAutoRefresh = isAutoRefresh;
}
/**
* 獲取是否正在計時
*
* @return
*/
public boolean isTiming() {
return isTiming;
}
/**
* 獲取計時是否暫停
*
* @return
*/
public boolean isPausing() {
return isPausing;
}
/**
* 計時回調接口
*/
public interface OnTimingListener {
/**
* 計時過程中回調
*
* @param hour 當前小時數
* @param minute 當前分鐘數
* @param second 當前秒數
* @param textView 當前控件實體
*/
void onTiming(String hour, String minute, String second, TextView textView);
/**
* 計時開始時回調
*/
void onStart();
/**
* 計時結束時回調,倒計時模式下才有此回調
*/
void onFinish();
}
/**
* 設置計時回調接口
* @param listener
*/
public void setOnTimingListener(OnTimingListener listener) {
this.listener = listener;
}
class TimingThread extends Thread {
@Override
public void run() {
time = isCountDown ? maxTime : 0;
isTiming = true;
isPausing = false;
sendMessage(TIME_START, handler);
do {
try {
if (isAutoRefresh) {
sendMessage(TIME_CHANGE, handler);
} else {
sendMessage(TIMING, handler);
}
time = isCountDown ? time - 1 : time + 1;
if (time >= 0) sleep(1000);
while (isPausing) {
sleep(500);
}
} catch (Exception e) {
e.printStackTrace();
}
} while (isTiming && (isCountDown ? time >= 0 : true));
isTiming = false;
time = 0;
sendMessage(TIME_FINISH, handler);
}
}
}
然後就能用了。上主頁面和佈局文件:
MainActivity.java:
public class MainActivity extends Activity {
private Button startButton, stopButton, pauseButton, resumeButton, resetButton;
private TimingTextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initData() {
}
private void initView() {
startButton = (Button) findViewById(R.id.start_button);
stopButton = (Button) findViewById(R.id.stop_button);
pauseButton = (Button) findViewById(R.id.pause_button);
resumeButton = (Button) findViewById(R.id.resume_button);
resetButton = (Button) findViewById(R.id.reset_button);
textView = (TimingTextView) findViewById(R.id.textview);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.start();
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.stop();
}
});
pauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.pause();
}
});
resumeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.resume();
}
});
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textView.reset();
}
});
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.min.timingtextview.TimingTextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:textColor="#3F51B5"
android:textSize="30sp" />
<Button
android:id="@+id/start_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="START" />
<Button
android:id="@+id/stop_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="STOP" />
<Button
android:id="@+id/pause_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="PAUSE" />
<Button
android:id="@+id/resume_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="RESUME" />
<Button
android:id="@+id/reset_button"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_margin="10dp"
android:text="RESET" />
</LinearLayout>
運行看一下效果:
當然控件支持一些參數設置,設置方法在源碼裏有詳細註釋,大家可以自己試一試,這裏做幾個簡單示範,添加代碼:
textView.setIsCountDown(false);
textView.setLanguageMode(TimingTextView.CHINESE);
再次運行:
如果還需要自定義顯示內容的話可以setIsAutoRefresh(false),讓內容不自動刷新,然後setOnTimingListener設置回調接口,在onTiming裏自行顯示想要的內容就好了。
最後附上源碼地址:點擊打開鏈接
這次的內容就到這裏,我們下次再見。