Android实现自定义倒计时view

前言

前几天一个朋友做一个商城限时抢购的界面,曾问过里边的倒计时应该如何去做比较好,因为倒计时要放到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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值