安卓CountDownTimer实现全民夺宝抢购倒计时和短信验证码倒计时
2016-04-21 23:43
681 查看
在sina里看到了什么全民夺宝的链接,然后忍不住1元的诱惑被坑了10多块,什么都没有抽到,但是还是有人抽到了不知道是不是坑爹的,然后也就动手做一下倒计时的功能。
先看全民夺宝:
说起这个功能是不是感觉so easy,然后就以此来搞2个倒计时效果,顺便也学习一下CountDownTimer的使用。
哈哈,看看今天实现的效果图:
Timer与TimerTask(Java实现)
方法二
TimerTask与Handler(不用Timer的改进型)
方法三
Handler与Message(不用TimerTask)
方法四
Handler与Thread(不占用UI线程)
方法五
Handler与Runnable(最简单型)
回顾了以前最常使用的5种方法是不是觉得还是比较麻烦,要说最好的也就第5种。
开始倒计时使用:CountDownTimer .start();
关闭:CountDownTimer .cancle();
这里拿两种情况来实现这功能,顺便也做成2个自定义view来使用。
布局界面图:
先看布局:
我们先来 做短信验证码的倒计时功能:
思路就是:给按钮监听是否可点击,并且动态改变显示的文字,从而实现倒计时的效果。
接下来是仿全民夺宝抢购倒计时功能:
实现思路:一整个view包含商品图片、商品描述,项目实际开发中会通过接口获取值,然后就是一个倒计时效果,倒计时结束后变为揭晓获奖答案。
就写到这里吧,困觉。
come on,enjoy it.
demo传送门: CountDownMaster
这里最后推荐一个倒计时控件:CountdownView
先看全民夺宝:
说起这个功能是不是感觉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
相关文章推荐
- ORM思想
- Salt Master报错:Minion did not return. [No response]
- 价值观作业
- AM335x(TQ335x)学习笔记——WM8960声卡驱动移植
- javaweb中HTTP协议
- android学习 一
- ARM六种寻址方式的汇编实现
- Linux 中断底半部机制
- Android的menu(菜单)按钮的使用(by 星空武哥)
- Linux下编写运行访问MYSQL的程序以及MYSQL在linux下的下载安装
- 20150116--Cookie+Session-02
- 机器人网站查询
- WEB服务器6--IIS架构补充篇
- 第八周——第九周学习总结
- Linux系统 工作笔记
- MySQL_Php.php
- codec-wm8960分析
- 有效回文串
- 杭州--4.21
- 数据挖掘导论--数据