前言
前几天一个朋友做一个商城限时抢购的界面,曾问过里边的倒计时应该如何去做比较好,因为倒计时要放到listview里边去,我就想自定义一个带有倒计时功能的view,这样用起来应该会方便一些。后来又完善了一下拿出来与大家分享。
实现思想
首先明确一下需求:要做成一个带有倒计时功能的view,要显示的格式是(时:分:秒)。
我们主要解决的问题有:
1.自定义layout选取和填充实现
2.倒计时的定时器选取
3.让它变得更好用
主要实现–CountDownView
继承LinearLayout,这里主要要是ViewGroup的实现类,
重写带有两个参数的构造方法如下:
public CountDownView(Context context, AttributeSet attrs){
super(context,attrs);
LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.countdownlayout,this);
tv_hour=(TextView) findViewById(R.id.tv_hour);
tv_min=(TextView) findViewById(R.id.tv_min);
tv_sec=(TextView) findViewById(R.id.tv_sec);
tv_divider1=(TextView) findViewById(R.id.tv_divider1);
tv_divider2=(TextView) findViewById(R.id.tv_divider2);
}
在构造方法中加载了一个已经写好的布局,我们要关注的主要就是时分秒这三个TextView,在下面的定时器回调方法onTick中要用他们来对时分秒进行显示。
定时器采用CountDownTimer,在onTick方法中对时间进行更新显示,CountDownTimer的用法可参考http://www.cnblogs.com/over140/archive/2011/12/20/2294220.html
我在CountDownView中定义了一个定时器的内部类,具体实现如下:
/* 定义一个倒计时的内部类 */
class MyCount extends CountDownTimer {
private String sec=null;
private String min=null;
private String hour=null;
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onFinish() {
//倒计时结束
}
@Override
public void onTick(long millisUntilFinished) {
if(onTimeChangeListener!=null&&(sec=onTimeChangeListener.onSecChange(millisUntilFinished / 1000%60))!=null){
tv_sec.setText(sec);
}else{
tv_sec.setText(millisUntilFinished / 1000%60+"");
}
//如果秒数=59则说明分钟数有变化,则对分进行设置
if(millisUntilFinished / 1000%60==59){
if(onTimeChangeListener!=null&&(min=onTimeChangeListener.onMinChange(millisUntilFinished/1000%(60*60)/60))!=null){
tv_min.setText(min);
}else{
tv_min.setText(millisUntilFinished/1000%(60*60)/60+"");
}
}
//如果分数=59并且秒数=59则说明小时数有变化,对小时数进行设置
if(millisUntilFinished/1000%(60*60)/60==59&&millisUntilFinished / 1000%60==59){
if(onTimeChangeListener!=null&&(hour=onTimeChangeListener.onHourChange(millisUntilFinished/1000/(60*60)))!=null){
tv_hour.setText(hour);
}else{
tv_hour.setText(millisUntilFinished/1000/(60*60)+"");
}
}
}
}
说明:我主要用到了onTick方法,因为我的单位是秒所以我在实例化的时候countDownInterval传入的是1000,其中的计算都是以秒为单位的。
实例化CountDownTimer所要用到的参数是毫秒数和时间间隔,这在时间比较长时会很不直观,所以我在CountDownView中暴露了一个方法,其参数是时、分、秒,并对CountDownTimer进行实例化,代码如下:
/**
* 为view设置初始时间,对时、分、秒分别设置,主要用这个来设置时间,比较实用
* @param hour
* @param min
* @param sec
*/
public void setCountDown(long hour,long min,long sec){
tv_hour.setText(hour+"");
tv_min.setText(min+"");
tv_sec.setText(sec+"");
mc = new MyCount(hour*60*60*1000+min*60*1000+sec*1000, 1000);
}
为了能在使用CountDownView时可以自定义时间的显示格式等,我给CountDownView添加了一个监听,在时、分、秒发生改变时分别回调三个方法,其实现如下:
/**
* 定义一个倒计时的监听接口,来监听时间变化
* @author fuxinpeng
*
*/
public interface OnTimeChangeListener{
String onHourChange(long hour);
String onMinChange(long min);
String onSecChange(long sec);
}
private OnTimeChangeListener onTimeChangeListener;
/**
* 设置实现了监听接口的类对象
* @param onTimeChangeListener
*/
public void setOnTimeChangeListener(OnTimeChangeListener onTimeChangeListener){
this.onTimeChangeListener=onTimeChangeListener;
}
说明:这个过程主要分4个步骤:
1.写一个监听的接口,声明将来要回调的方法
2.把实现了该接口的类对象作为CountDownView的属性
3.为这个属性写一个set方法
4.在CountDownView中使用该方法,当程序执行到该方法的时候就会产生回调。
拿OnTimeChangeListener接口的onSecChange方法为例,在我定义的onTick中有这样一段代码:
if(onTimeChangeListener!=null&&(sec=onTimeChangeListener.onSecChange(millisUntilFinished / 1000%60))!=null){
tv_sec.setText(sec);
}else{
tv_sec.setText(millisUntilFinished / 1000%60+"");
}
这段代码说的是如果监听不为null,并且onSecChange返回的不是null(默认返回null),则在秒数的TextView中显示传回的经过了格式化之后的字符串(回调返回值)。
用法
用法的代码如下:
public class MainActivity extends Activity {
private CountDownView countDownView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViews();
//设置倒计时总时间 参数:时、分、秒
countDownView.setCountDown(1,0,10);
//设置字体大小
countDownView.setTextSize(30);
//添加倒计时监听,回调了三个方法,可以在时间改变的时候做些操作,比如按照自己的要求做相应的操作
countDownView.setOnTimeChangeListener(new CountDownView.OnTimeChangeListener() {
@Override
public String onSecChange(long sec) {
String mysec=sec+"秒";
return mysec;
}
@Override
public String onMinChange(long min) {
// TODO Auto-generated method stub
return null;
}
@Override
public String onHourChange(long hour) {
// TODO Auto-generated method stub
return null;
}
});
countDownView.start();
}
private void findViews() {
countDownView=(CountDownView) findViewById(R.id.myview);
}
}
说明:
1.设置倒计时时间
2.设置显示格式(可选)
3.添加监听(可选)重写方法将格式化后的时间返回,返回null则使用默认格式。
4.调用start()来启动倒计时(封装了CountDownTimer的start方法)
demo分享
云资源链接http://pan.baidu.com/s/1qWosWcG
CSDN资源链接http://download.csdn.net/detail/litterfrog/9207825