前言:这几天博客积的有点多,工作也是忙的够呛.
先上本篇效果图:
就是自定义一个能倒计时的TextView控件,当我们点击start run按钮时,给他传进去一个时间数字,它自己开始倒计时,不需要外部任何干预。当点击Stop run按钮时,停止倒计时。
一、自定义倒计时控件——TimerTextView
显然TimerTextView应该派生于TextView,因为他本就是显示一串Text,只是具有了自动更新的功能,这里的自动更新的实现当然只通过线程来实现了,所以要继承Runnable接口。所以它的定义应该是这样的:
-
public
class
TimerTextView
extends
TextView
implements
Runnable{ -
public
TimerTextView(Context context, AttributeSet attrs) { -
super
(context, attrs); -
// TODO Auto-generated constructor stub
- }
-
@Override
-
public
void
run() { -
//自动更新
- }
- }
public class TimerTextView extends TextView implements Runnable{
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
public void run() {
//自动更新
}
}
首先,要给外部提供一个函数,可以给它设置要开始倒计时的数字:
-
private
long
mday, mhour, mmin, msecond;
//天,小时,分钟,秒
private long mday, mhour, mmin, msecond;//天,小时,分钟,秒
-
public
void
setTimes(
long
[] times) { -
mday = times[
0
]; -
mhour = times[
1
]; -
mmin = times[
2
]; -
msecond = times[
3
]; - }
public void setTimes(long[] times) {
mday = times[0];
mhour = times[1];
mmin = times[2];
msecond = times[3];
}
然后要实现当前线程的开始和终止,相关实现是下面几个函数:
-
private
boolean
run=
false
;
//是否启动了
private boolean run=false; //是否启动了
-
public
boolean
isRun() { -
return
run; - }
-
public
void
beginRun() { -
this
.run =
true
; - run();
- }
-
public
void
stopRun(){ -
this
.run =
false
; - }
public boolean isRun() {
return run;
}
public void beginRun() {
this.run = true;
run();
}
public void stopRun(){
this.run = false;
}
这里定义一个变量run来标识当前线程是否已经启动,如果没有启动,我们可以调用beginRun()来开始线程,在beginRun()函数中,调用run()开线程开始运行,在线程中,我们就要实现一秒更新一次当前数字了:
-
@Override
-
public
void
run() { -
//标示已经启动
-
if
(run){ - ComputeTime();
-
String strTime= mday +
“天:”
+ mhour+
“小时:”
+ mmin+
“分钟:”
+msecond+
“秒”
; -
this
.setText(strTime); -
postDelayed(
this
,
1000
); -
}
else
{ -
removeCallbacks(
this
); - }
- }
@Override
public void run() {
//标示已经启动
if(run){
ComputeTime();
String strTime= mday +"天:"+ mhour+"小时:"+ mmin+"分钟:"+msecond+"秒";
this.setText(strTime);
postDelayed(this, 1000);
}else {
removeCallbacks(this);
}
}
首先判断当前线程应该具有的状态,如果还是在跑着(即run变量为true),那就计算当前应该显示的时间(ComputeTime()函数),然后设置给自己。最后利用postDelayed(this,1000),来延长1秒后再运行一次。
如果用户调用了StopRun()函数,将run变量置为了FALSE,即用户要停止线程运行,这里,我们调用removeCallbacks(this)来终止当前线程。
下面就是看看如何来计算当前要显示的时间的omputeTime()函数了:
-
private
void
ComputeTime() { - msecond–;
-
if
(msecond <
0
) { - mmin–;
-
msecond =
59
; -
if
(mmin <
0
) { -
mmin =
59
; - mhour–;
-
if
(mhour <
0
) { -
// 倒计时结束
-
mhour =
24
; - mday–;
- }
- }
- }
- }
private void ComputeTime() {
msecond--;
if (msecond < 0) {
mmin--;
msecond = 59;
if (mmin < 0) {
mmin = 59;
mhour--;
if (mhour < 0) {
// 倒计时结束
mhour = 24;
mday--;
}
}
}
}
理解起来应该没什么难度,秒一次减一,如果减到0,一方面重置为59,另一方面分钟要减一,当分钟减到0时,一方面分钟置为59,一方面小时减一,天的计划一样,需要注意的是,一天是24个小时哦,不是60。
OK啦,重写控件的部分就讲完了,下面列出这块的完整代码,供大家参考:
-
public
class
TimerTextView
extends
TextView
implements
Runnable{ -
public
TimerTextView(Context context, AttributeSet attrs) { -
super
(context, attrs); -
// TODO Auto-generated constructor stub
- }
-
private
long
mday, mhour, mmin, msecond;
//天,小时,分钟,秒
-
private
boolean
run=
false
;
//是否启动了
-
public
void
setTimes(
long
[] times) { -
mday = times[
0
]; -
mhour = times[
1
]; -
mmin = times[
2
]; -
msecond = times[
3
]; - }
-
/**
-
* 倒计时计算
-
*/
-
private
void
ComputeTime() { - msecond–;
-
if
(msecond <
0
) { - mmin–;
-
msecond =
59
; -
if
(mmin <
0
) { -
mmin =
59
; - mhour–;
-
if
(mhour <
0
) { -
// 倒计时结束,一天有24个小时
-
mhour =
23
; - mday–;
- }
- }
- }
- }
-
public
boolean
isRun() { -
return
run; - }
-
public
void
beginRun() { -
this
.run =
true
; - run();
- }
-
public
void
stopRun(){ -
this
.run =
false
; - }
-
@Override
-
public
void
run() { -
//标示已经启动
-
if
(run){ - ComputeTime();
-
String strTime= mday +
“天:”
+ mhour+
“小时:”
+ mmin+
“分钟:”
+msecond+
“秒”
; -
this
.setText(strTime); -
postDelayed(
this
,
1000
); -
}
else
{ -
removeCallbacks(
this
); - }
- }
- }
public class TimerTextView extends TextView implements Runnable{
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
private long mday, mhour, mmin, msecond;//天,小时,分钟,秒
private boolean run=false; //是否启动了
public void setTimes(long[] times) {
mday = times[0];
mhour = times[1];
mmin = times[2];
msecond = times[3];
}
/**
* 倒计时计算
*/
private void ComputeTime() {
msecond--;
if (msecond < 0) {
mmin--;
msecond = 59;
if (mmin < 0) {
mmin = 59;
mhour--;
if (mhour < 0) {
// 倒计时结束,一天有24个小时
mhour = 23;
mday--;
}
}
}
}
public boolean isRun() {
return run;
}
public void beginRun() {
this.run = true;
run();
}
public void stopRun(){
this.run = false;
}
@Override
public void run() {
//标示已经启动
if(run){
ComputeTime();
String strTime= mday +"天:"+ mhour+"小时:"+ mmin+"分钟:"+msecond+"秒";
this.setText(strTime);
postDelayed(this, 1000);
}else {
removeCallbacks(this);
}
}
}
二、控件使用
下面我们就在MainActivity中使用一下,先看看MainActivity的布局(activity_main.xml)
从最开头的演示中也可以看出,使用的是垂直布局,两个BTN,一个倒计时TextView
-
<
LinearLayout
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”
-
android:orientation
=
“vertical”
-
tools:context
=
“com.example.trytimerview.MainActivity”
>
-
<
Button
android:id
=
“@+id/main_start_btn”
-
android:layout_width
=
“match_parent”
-
android:layout_height
=
“wrap_content”
-
android:text
=
“start run”
/>
-
<
Button
android:id
=
“@+id/main_stop_btn”
-
android:layout_width
=
“match_parent”
-
android:layout_height
=
“wrap_content”
-
android:text
=
“stop run”
/>
-
<
com.example.trytimerview.TimerTextView
-
android:id
=
“@+id/timer_text_view”
-
android:layout_width
=
“fill_parent”
-
android:layout_height
=
“wrap_content”
-
android:textSize
=
“18sp”
-
android:textColor
=
“#ff0000”
-
android:gravity
=
“center_horizontal”
-
android:text
=
“倒计时”
-
/>
-
</
LinearLayout
>
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.trytimerview.MainActivity" >
<Button android:id="@+id/main_start_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start run"/>
<Button android:id="@+id/main_stop_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stop run"/>
<com.example.trytimerview.TimerTextView
android:id="@+id/timer_text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textColor="#ff0000"
android:gravity="center_horizontal"
android:text="倒计时"
/>
</LinearLayout>
然后是在MainActivity中,先列出整体的代码,然后再细讲:
-
public
class
MainActivity
extends
Activity { -
@Override
-
protected
void
onCreate(Bundle savedInstanceState) { -
super
.onCreate(savedInstanceState); - setContentView(R.layout.activity_main);
-
//初始化倒计时控件
-
final
TimerTextView timerTextView = (TimerTextView)findViewById(R.id.timer_text_view); -
long
[] times = {
0
,
10
,
5
,
30
}; - timerTextView.setTimes(times);
- Button startBtn = (Button)findViewById(R.id.main_start_btn);
- Button stopBtn = (Button)findViewById(R.id.main_stop_btn);
-
//开始倒计时
-
startBtn.setOnClickListener(
new
View.OnClickListener() { -
@Override
-
public
void
onClick(View v) { -
// TODO Auto-generated method stub
-
if
(!timerTextView.isRun()){ - timerTextView.beginRun();
- }
- }
- });
-
//停止倒计时
-
stopBtn.setOnClickListener(
new
View.OnClickListener() { -
@Override
-
public
void
onClick(View v) { -
// TODO Auto-generated method stub
-
if
(timerTextView.isRun()){ - timerTextView.stopRun();
- }
- }
- });
- }
- }
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化倒计时控件
final TimerTextView timerTextView = (TimerTextView)findViewById(R.id.timer_text_view);
long[] times = {0,10,5,30};
timerTextView.setTimes(times);
Button startBtn = (Button)findViewById(R.id.main_start_btn);
Button stopBtn = (Button)findViewById(R.id.main_stop_btn);
//开始倒计时
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!timerTextView.isRun()){
timerTextView.beginRun();
}
}
});
//停止倒计时
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(timerTextView.isRun()){
timerTextView.stopRun();
}
}
});
}
}
这里首先是,初始化TimerTextView控件:
初始化为从10个小时,5分钟,30秒开始倒计时
-
final
TimerTextView timerTextView = (TimerTextView)findViewById(R.id.timer_text_view); -
long
[] times = {
0
,
10
,
5
,
30
}; - timerTextView.setTimes(times);
final TimerTextView timerTextView = (TimerTextView)findViewById(R.id.timer_text_view);
long[] times = {0,10,5,30};
timerTextView.setTimes(times);
然后当用户点击StartRun按钮时,先判断当前是否在运行,如果没在运行,就让它开始跑起来:
-
startBtn.setOnClickListener(
new
View.OnClickListener() { -
@Override
-
public
void
onClick(View v) { -
// TODO Auto-generated method stub
-
if
(!timerTextView.isRun()){ - timerTextView.beginRun();
- }
- }
- });
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(!timerTextView.isRun()){
timerTextView.beginRun();
}
}
});
当用户点击Stop Run按钮时,停止运行:
-
stopBtn.setOnClickListener(
new
View.OnClickListener() { -
@Override
-
public
void
onClick(View v) { -
// TODO Auto-generated method stub
-
if
(timerTextView.isRun()){ - timerTextView.stopRun();
- }
- }
- });
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(timerTextView.isRun()){
timerTextView.stopRun();
}
}
});
OK啦,这篇比较简单,代码量也比较小,就不再多说了。
如果这篇文章有帮到你,记得关注哦
源码下载地址:
http://download.csdn.net/detail/harvic880925/8271087
请大家尊重原创者版权,转载请标时出处:
http://blog.csdn.net/harvic880925/article/details/41977569
谢谢。