安卓CountDownTimer实现全民夺宝抢购倒计时和短信验证码倒计时

在sina里看到了什么全民夺宝的链接,然后忍不住1元的诱惑被坑了10多块,什么都没有抽到,但是还是有人抽到了不知道是不是坑爹的,然后也就动手做一下倒计时的功能。

先看全民夺宝:

说起这个功能是不是感觉so easy,然后就以此来搞2个倒计时效果,顺便也学习一下CountDownTimer的使用。

哈哈,看看今天实现的效果图:

回顾 常用的倒计时方式

方法一

Timer与TimerTask(Java实现)

public class timerTask extends Activity{
    private int recLen = 11;
    private TextView txtView;
    Timer timer = new Timer();
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);  

        setContentView(R.layout.timertask);
        txtView = (TextView)findViewById(R.id.txttime);  

        timer.schedule(task, 1000, 1000);       // timeTask
    }
    TimerTask task = new TimerTask() {
        @Override
        public void run() {  

            runOnUiThread(new Runnable() {      // UI thread
                @Override
                public void run() {
                    recLen--;
                    txtView.setText(""+recLen);
                    if(recLen < 0){
                        timer.cancel();
                        txtView.setVisibility(View.GONE);
                    }
                }
            });
        }
    };
}  

方法二

TimerTask与Handler(不用Timer的改进型)

public class timerTask extends Activity{
    private int recLen = 11;
    private TextView txtView;
    Timer timer = new Timer();  

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);  

        setContentView(R.layout.timertask);
        txtView = (TextView)findViewById(R.id.txttime);  

        timer.schedule(task, 1000, 1000);       // timeTask
    }     

    final Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            switch (msg.what) {
            case 1:
                txtView.setText(""+recLen);
                if(recLen < 0){
                    timer.cancel();
                    txtView.setVisibility(View.GONE);
                }
            }
        }
    };  

    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            recLen--;
            Message message = new Message();
            message.what = 1;
            handler.sendMessage(message);
        }
    };
}  

方法三

Handler与Message(不用TimerTask)

public class timerTask extends Activity{
    private int recLen = 11;
    private TextView txtView;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.timertask);
        txtView = (TextView)findViewById(R.id.txttime);
        Message message = handler.obtainMessage(1);     // Message
        handler.sendMessageDelayed(message, 1000);
    }
    final Handler handler = new Handler(){
        public void handleMessage(Message msg){         // handle message
            switch (msg.what) {
            case 1:
                recLen--;
                txtView.setText("" + recLen);
                if(recLen > 0){
                    Message message = handler.obtainMessage(1);
                    handler.sendMessageDelayed(message, 1000);      // send message
                }else{
                    txtView.setVisibility(View.GONE);
                }
            }
            super.handleMessage(msg);
        }
    };
}  

方法四

Handler与Thread(不占用UI线程)

public class timerTask extends Activity{
    private int recLen = 11;
    private TextView txtView;
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.timertask);
        txtView = (TextView)findViewById(R.id.txttime);
        new Thread(new MyThread()).start();         // start thread
    }
    final Handler handler = new Handler(){          // handle
        public void handleMessage(Message msg){
            switch (msg.what) {
            case 1:
                recLen--;
                txtView.setText("" + recLen);
            }
            super.handleMessage(msg);
        }
    };
    public class MyThread implements Runnable{      // thread
        @Override
        public void run(){
            while(recLen>0){
                try{
                    Thread.sleep(1000);     // sleep1000ms
                    Message message = new Message();
                    message.what = 1;
                    handler.sendMessage(message);
                }catch (Exception e) {
                }  

方法五

Handler与Runnable(最简单型)

public class timerTask extends Activity{
    private int recLen = 11;
    private TextView txtView;
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.timertask);
        txtView = (TextView)findViewById(R.id.txttime);
        handler.postDelayed(runnable, 1000);
    }     

    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            if(recLen>0){
             recLen--;
            }
            txtView.setText("" + recLen);
            handler.postDelayed(this, 1000);
        }
    };
}  

回顾了以前最常使用的5种方法是不是觉得还是比较麻烦,要说最好的也就第5种。

CountDownTimer 实现倒计时功能

使用案列(简单)

     /**
       * 继承 CountDownTimer 防范
       *
       * 重写 父类的方法 onTick() 、 onFinish()
       */

      class MyCountDownTimer extends CountDownTimer {
        /**
         * @param millisInFuture
         *      表示以毫秒为单位 倒计时的总数
         *      例如 millisInFuture=1000 表示1秒
         * @param countDownInterval
         *      表示 间隔 多少微秒 调用一次 onTick 方法
         *      例如: countDownInterval =1000 ; 表示每1000毫秒调用一次onTick()
         *
         */
        public MyCountDownTimer(long millisInFuture, long countDownInterval) {
          super(millisInFuture, countDownInterval);
        } 

        @Override
        public void onFinish() {
          .....//记时结束处理
        } 

        @Override
        public void onTick(long millisUntilFinished) {
            .....//计时过程中的处理
            }
        }
      } 

开始倒计时使用:CountDownTimer .start();

关闭:CountDownTimer .cancle();

这里拿两种情况来实现这功能,顺便也做成2个自定义view来使用。

布局界面图:

先看布局:

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context="com.losileeya.countdownmaster.MainActivity"
    android:layout_marginTop="20dp"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:background="#AAA9AA">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="场景一:商品抢购"
        android:textSize="24sp"
        android:textColor="#D93552"
        />
    <com.losileeya.countdownmaster.view.CommodityBuyView
        android:id="@+id/commodityBuyView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="场景二:短信验证码"
        android:textSize="24sp"
        android:textColor="#D93552"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:orientation="vertical">
        <EditText
            android:id="@+id/et_phone"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/code_bg"
            android:hint="请输入手机号"
            android:padding="10dp"
            android:layout_marginLeft="30dp"
            android:layout_marginRight="30dp"
            android:maxLength="11"
            android:textSize="16sp"/>
        <LinearLayout
            android:layout_marginTop="10dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            >
            <EditText
                android:id="@+id/et_msg_code"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_weight="1"
                android:background="@drawable/code_bg"
                android:layout_marginLeft="50dp"
                android:gravity="center"
                />
            <com.losileeya.countdownmaster.view.TimeButton
                android:id="@+id/time_button"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:layout_gravity="center"
                >
          </com.losileeya.countdownmaster.view.TimeButton>
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

我们先来 做短信验证码的倒计时功能:

思路就是:给按钮监听是否可点击,并且动态改变显示的文字,从而实现倒计时的效果。

package com.losileeya.countdownmaster.view;
import android.content.Context;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import com.losileeya.countdownmaster.R;
/**
 * 自定义控件,实现验证码按钮倒计时功能。
 * losileeya
 *
 */
public class TimeButton extends LinearLayout {
    private Button timeButton;
    private int default_time = 60*1000;//默认时间
    private TimeButtonCallBack timeButtoncallback;//倒计时按钮回掉接口
    private MyCountDownTimer mc; //倒计时线程
    public TimeButton(Context context) {
        this(context, null);
    }

    public TimeButton(Context context, AttributeSet attrs)    {
        this(context, attrs, 0);
    }
    public TimeButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
         LayoutInflater inflater = (LayoutInflater) context
         .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        //把view和布局绑定
         timeButton = (Button) inflater.inflate(R.layout.view_time_button, this).findViewById(R.id.time);
         initListerner();
    }

    /**
     * 暴露倒计时时间给使用者调
     * @param millis
     */
    public void setTime(int millis){
         this.default_time= millis;
     }
    public void initListerner() {
        timeButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (timeButtoncallback != null) {
                    if (timeButtoncallback.Start()) {
                        // 手机号验证通过了,那么继续下面的操作。
                    } else {
                        // 手机号验证未通过,直接返回了,不执行下面的操作。
                        return;
                    }
                } else {
                    // 回调接口为空,有问题,直接返回了,不执行下面的操作。
                    return;
                }
                timeButton.setClickable(false);
                mc = new MyCountDownTimer(default_time, 1000);
                mc.start(); //倒计时记时
            }
        });
    }

    public void setTimeButtonCallBack(TimeButtonCallBack timeButtoncallback) {
        this.timeButtoncallback = timeButtoncallback;
    }

    /**
     * 倒计时控件回调外部代码的接口。
     *
     *
     */
    public interface TimeButtonCallBack {

        /**
         * 点击按钮后,开始计时前调用的方法。
         *
         * @return 返回true会开始计时,false会退出计时。
         */
        public boolean Start();

        /**
         * 结束啦。
         */
        public void End();

        /**
         * 数字发生变化了。
         *
         * @param num
         * @return
         */
        public void numChanged(int num);

    }
    /**
       * 继承 CountDownTimer 防范
       *
       * 重写 父类的方法 onTick() 、 onFinish()
       */

      class MyCountDownTimer extends CountDownTimer {
        /**
         *
         * @param millisInFuture
         *      表示以毫秒为单位 倒计时的总数
         *
         *      例如 millisInFuture=1000 表示1秒
         *
         * @param countDownInterval
         *      表示 间隔 多少微秒 调用一次 onTick 方法
         *
         *      例如: countDownInterval =1000 ; 表示每1000毫秒调用一次onTick()
         *
         */
        public MyCountDownTimer(long millisInFuture, long countDownInterval) {
          super(millisInFuture, countDownInterval);
        } 

        @Override
        public void onFinish() {
            mc.cancel();
            timeButton.setText("获取验证码");
            timeButton.setClickable(true);
            if (timeButtoncallback != null) {
                timeButtoncallback.End();
            }
        } 

        @Override
        public void onTick(long millisUntilFinished) {
            timeButton.setText(millisUntilFinished/1000 + "秒后重新获取");
            if (timeButtoncallback != null) {
                timeButtoncallback.numChanged((int)millisUntilFinished/1000);
            }
        }
      }
}

接下来是仿全民夺宝抢购倒计时功能:

实现思路:一整个view包含商品图片、商品描述,项目实际开发中会通过接口获取值,然后就是一个倒计时效果,倒计时结束后变为揭晓获奖答案。

package com.losileeya.countdownmaster.view;
import android.content.Context;
import android.os.CountDownTimer;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.losileeya.countdownmaster.R;
/**
 * Created by losileeya on 2016/4/21.
 */
public class CommodityBuyView extends LinearLayout {
    private TextView tv_goods_desc,tv_status,tv_awardee;
    private MyCountDownTimer mc;
    private LinearLayout ll_result;
    private String awardee;
    public CommodityBuyView(Context context) {
        this(context, null);
    }

    public CommodityBuyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CommodityBuyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    /**
     * find 控件,初始化
     * @param context
     */
    private void initView(Context context) {
        LayoutInflater inflater = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    //通过LayoutInflater  打气筒填补当前自定义view的布局。this表示attach到父控件
 View view=inflater.inflate(R.layout.view_commodity_buying,this);
tv_goods_desc= (TextView)view.findViewById(R.id.tv_goods_desc);
 tv_status= (TextView) view.findViewById(R.id.tv_status);
tv_awardee= (TextView) view.findViewById(R.id.tv_awardee);
ll_result= (LinearLayout) view.findViewById(R.id.ll_result);
tv_status=(TextView) view.findViewById(R.id.tv_status);
        //这里为了显示出毫秒,所以0.1秒倒计时一次
        mc = new MyCountDownTimer(280000, 100);
        mc.start();
    }
    /**
     * 继承 CountDownTimer 防范
     *
     * 重写 父类的方法 onTick() 、 onFinish()
     */

    class MyCountDownTimer extends CountDownTimer {
        /**
         *
         * @param millisInFuture
         *      表示以毫秒为单位 倒计时的总数
         *
         *      例如 millisInFuture=1000 表示1秒
         *
         * @param countDownInterval
         *      表示 间隔 多少微秒 调用一次 onTick 方法
         *
         *      例如: countDownInterval =1000 ; 表示每1000毫秒调用一次onTick()
         *
         */
        public MyCountDownTimer(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }
        @Override
        public void onFinish() {
            tv_status.setText("揭晓中....");
               new Handler().postDelayed(new Runnable() {
                   @Override
                   public void run() {
                        //倒计时隐藏
                     tv_status.setVisibility(View.GONE);
                    //获奖结果显示
                    ll_result.setVisibility(View.VISIBLE);
                       //延迟5秒后公布获奖人
                    tv_awardee.setText(awardee);
                   }
               }, 5000);
        }
        /**
         * 处理时间倒计时进行页面刷新
         * @param millisUntilFinished
         */
        @Override
        public void onTick(long millisUntilFinished) {
            int ss = 1000;
            int mi = ss * 60;
            long minute = millisUntilFinished/ mi;//计算分钟
            long second = (millisUntilFinished- minute * mi) / ss;//总时间-分钟的毫秒数得到秒数
            long milliSecond = millisUntilFinished  - minute * mi - second * ss;//获得毫秒数
            String strMinute = minute < 10 ? "0" + minute : "" + minute;//分钟
            String strSecond = second < 10 ? "0" + second : "" + second;//秒
            String strMilliSecond = milliSecond < 10 ? "0" + milliSecond : "" + milliSecond;//毫秒不满十前面补0
            strMilliSecond = milliSecond >100 ? strMilliSecond.substring(0,strMilliSecond.length()-1) : "" + strMilliSecond;////毫秒超过100显示前2位
            //显示分秒毫秒的倒计时
            tv_status.setText(strMinute + " 分 "+strSecond+"秒"+strMilliSecond);
        }
    }
    /**
     * 设置获奖人
     * @param awardee
     */
    public void setAwardee(String awardee){
        this.awardee= awardee;
    }
}

就写到这里吧,困觉。

总结

其实代码是很简单的,但是效果也还算可以的,项目过程中也或许用得到,至少很多人可能都不知道CountDownTimer这个东东,所以兴趣是最好的老师。如果你觉得还行的话,帮忙顶起来这将是对我最大的鼓励。

come on,enjoy it.

demo传送门: CountDownMaster

这里最后推荐一个倒计时控件:CountdownView

时间: 2024-12-24 18:36:05

安卓CountDownTimer实现全民夺宝抢购倒计时和短信验证码倒计时的相关文章

短信验证码倒计时

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="yan.aspx.cs" Inherits="Technology.yan" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"><head runat="server&

js 发送短信验证码倒计时

html <input type="button" id="btn" value="免费获取验证码" onclick="settime(this)" /> js // 短信验证码倒计时var countdown=60;function settime(obj) { if (countdown == 0) { obj.removeAttribute("disabled"); obj.value=&

Android获取短信验证码倒计时

目前越来越多的app在注册或是进行对应操作时,要求获取短信验证码,在点击了获取短信验证码的按钮后,就是出现倒计时,比如倒计时120S,在倒计时期间内,按钮点击是无效的,当倒计时结束后,如果你没有获取到验证码,可以再次点击.实现倒计时的方法很多,我们今天就通过继承android.os.CountDownTimer类来实现! 首先看下我们封装的倒计时工具类,主要为了在多个地方用到的话,用了多个构造方法,就是为了使用更灵活,只要传入对数就可以调用了: public class MyCountTimer

iOS 短信验证码倒计时按钮的实现

验证码倒计时按钮的应用是非常普遍的,本文介绍了IOS实现验证码倒计时功能,点击获取验证码,进入时间倒计时,感兴趣的小伙伴们可以参考一下: 实现思路: 创建按钮,添加点击方法: 用NSTimer定时器,每秒执行一次,定时改变Button的title,改变Button的样式,设置Button不可点击: 若倒计时结束,定时器关闭,并改变Button的样式,可以点击: 代码如下: 在按钮的点击事件里调用该方法      -(void)openCountdown{ __block NSInteger ti

发送短信验证码 倒计时

1.页面样式:基于bootstrap 1 <div class="form-group"> 2 <label class="col-md-4 control-label">手机号码</label> 3 <div class="col-md-8"> 4 <div class="input-group m-b"> 5 <input class="form-

android 获取短信验证码倒计时

public class MainActivity extends Activity { private Button submit; private TimeCount time; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentVi

js,JQ获取短信验证码倒计时

按钮 <a href="javasript:void(0);"onclick="settime(this);">获取手机验证码</a> 倒计时js <script> var countdown=60; function settime(obj) { if (countdown == 0) { obj.getAttributeNode('onclick').value ="settime(this);"; obj

发送短信验证码倒计时&amp;&amp;防止刷新

html代码 <input type="button" id="btn" class="sms-btn" onclick="sendPh()" value='获取验证码' /> js代码 倒计时function timekeeping(){//把按钮设置为不可以点击$('#btn').attr("disabled", true);var interval=setInterval(function

获取短信验证码倒计时

<input type="button" id="btn" value="免费获取验证码" /> <script type="text/javascript"> var wait=60; function time(o) { if (wait == 0) { o.removeAttribute("disabled"); o.value="免费获取验证码"; wai