一、首先要创建一个自定义的TextView
- 创建一个继承TextView的控件
- 资源布局中引用该控件
创建自定义的TextView控件
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
public class TimerTextView extends TextView {
public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TimerTextView(Context context) {
super(context);
}
}
在布局中引用该控件
<RelativeLayout 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"
tools:context="${relativePackage}.${activityClass}" >
<com.example.timertextviewdemo.TimerTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
二、完善这个TimerTextView加入倒计时功能。
要另启用一个线程,来实现倒计时的功能。首先要实现Runnable接口。为了控制这个倒计时,需要有个isRun变量,查看程序是否正在运行。提供一个start和stop方法来控制计时器。
第二部主要实现倒计时功能。需要一个setTimes和countdown方法。如下:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
public class TimerTextView extends TextView implements Runnable {
// 时间变量
private int day, hour, minute, second;
// 当前计时器是否运行
private boolean isRun = false;
public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TimerTextView(Context context) {
super(context);
}
/**
* 将倒计时时间毫秒数转换为自身变量
*
* @param time
* 时间间隔毫秒数
*/
public void setTimes(long time) {
}
/**
* 显示当前时间
*
* @return
*/
public String showTime() {
return null;
}
/**
* 实现倒计时
*/
private void countdown() {
}
public boolean isRun() {
return isRun;
}
/**
* 开始计时
*/
public void start() {
}
/**
* 结束计时
*/
public void stop() {
}
/**
* 实现计时循环
*/
@Override
public void run() {
}
}
我们来一点一点实现他的功能。首页我们要将时间传递给计时器。这个time代表两个date时间差的毫秒数。最后我们将毫秒数转换成时间,存到变量中。
/**
* 将倒计时时间毫秒数转换为自身变量
*
* @param time
* 时间间隔毫秒数
*/
public void setTimes(long time) {
//将毫秒数转化为时间
this.second = (int) (time / 1000) % 60;
this.minute = (int) (time / (60 * 1000) % 60);
this.hour = (int) (time / (60 * 60 * 1000) % 24);
this.day = (int) (time / (24 * 60 * 60 * 1000));
}
之后我们可以用变量来实现倒计时功能。
由各时间的变量可以得出他们值的范围:
秒:0~59
分钟:0~59
小时:0~24
天:0~
每次调用countdown方法时,秒就会减1.这里边界判断,当秒为0的时候,需要向分钟借1位,如果分钟也为0,则需要向小时借1位。依次类推,所有变量均为0时,停止倒计时。
/**
* 实现倒计时
*/
private void countdown() {
if (second == 0) {
if (minute == 0) {
if (hour == 0) {
if (day == 0) {
//当时间归零时停止倒计时
isRun = false;
return;
} else {
day--;
}
hour = 23;
} else {
hour--;
}
minute = 59;
} else {
minute--;
}
second = 60;
}
second--;
}
接下来实现run方法,调用countdown
/**
* 实现计时循环
*/
@Override
public void run() {
if (isRun) {
countdown();
this.setText(showTime());
postDelayed(this, 1000);
} else {
removeCallbacks(this);
}
}
isRun判断计时器是否运行
完整的类实现如下:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
public class TimerTextView extends TextView implements Runnable {
// 时间变量
private int day, hour, minute, second;
// 当前计时器是否运行
private boolean isRun = false;
public TimerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public TimerTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TimerTextView(Context context) {
super(context);
}
/**
* 将倒计时时间毫秒数转换为自身变量
*
* @param time
* 时间间隔毫秒数
*/
public void setTimes(long time) {
//将毫秒数转化为时间
this.second = (int) (time / 1000) % 60;
this.minute = (int) (time / (60 * 1000) % 60);
this.hour = (int) (time / (60 * 60 * 1000) % 24);
this.day = (int) (time / (24 * 60 * 60 * 1000));
}
/**
* 显示当前时间
*
* @return
*/
public String showTime() {
StringBuilder time = new StringBuilder();
time.append(day);
time.append("天");
time.append(hour);
time.append("小时");
time.append(minute);
time.append("分钟");
time.append(second);
time.append("秒");
return time.toString();
}
/**
* 实现倒计时
*/
private void countdown() {
if (second == 0) {
if (minute == 0) {
if (hour == 0) {
if (day == 0) {
//当时间归零时停止倒计时
isRun = false;
return;
} else {
day--;
}
hour = 23;
} else {
hour--;
}
minute = 59;
} else {
minute--;
}
second = 60;
}
second--;
}
public boolean isRun() {
return isRun;
}
/**
* 开始计时
*/
public void start() {
isRun = true;
run();
}
/**
* 结束计时
*/
public void stop() {
isRun = false;
}
/**
* 实现计时循环
*/
@Override
public void run() {
if (isRun) {
// Log.d(TAG, "Run");
countdown();
this.setText(showTime());
postDelayed(this, 1000);
} else {
removeCallbacks(this);
}
}
}
在activity中调用这个控件
package com.example.timertextviewdemo;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
private TimerTextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy/MM/dd HH:mm:ss");
//获得当前时间
Date now = new Date();
//目标时间
Date target = null;
try {
target = dateFormat.parse("2015/6/22 11:37:00");
} catch (ParseException e) {
e.printStackTrace();
}
//获得时间差
long diff = target.getTime() - now.getTime();
mTextView = (TimerTextView) findViewById(R.id.timerTextView);
//设置时间
mTextView.setTimes(diff);
/**
* 开始倒计时
*/
if(!mTextView.isRun()){
mTextView.start();
}
}
}
简单的修改一下Textview的样式
<RelativeLayout 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"
tools:context="${relativePackage}.${activityClass}" >
<com.example.timertextviewdemo.TimerTextView
android:id="@+id/timerTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/green_detail_btn"
android:textSize="25sp"
android:textColor="@android:color/white"
android:gravity="center"/>
</RelativeLayout>
最后效果:
程序源码如下: