欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义Chronometer实现短信验证码秒表倒计时功能

程序员文章站 2024-03-01 15:09:34
本文实例为大家分享了chronometer实现倒计时功能,android提供了实现按照秒计时的api,供大家参考,具体内容如下 一、自定义chronometerview...

本文实例为大家分享了chronometer实现倒计时功能,android提供了实现按照秒计时的api,供大家参考,具体内容如下

一、自定义chronometerview 继续自textview

主要原理:先设置一个基准倒计时时间mbaseseconds,内置handler 每隔1s发送一个空消息,mremainseconds--,同时刷新界面视图,回调给外部调用者,只到为零。外部调用者可通过start()/pause()/stop()来控制计时器的工作状态。
可以app中发送短信验证码的场景为例,做了一个很粗糙的界面,但功能都实现了。

Android自定义Chronometer实现短信验证码秒表倒计时功能

/** 
 * @name 倒计时器(类似妙表倒数计时,支持暂停、停止、重新开始) 
 * @author fanjb 
 * @date 2015年11月6日 
 */ 
public class chronometerview extends textview { 
 
 /** 
 * a callback that notifies when the chronometer has decremented on its own. 
 * 
 * @author fanjb 
 */ 
 public interface ontickchangelistener { 
 
 /** 
  * remain seconds changed 
  * 
  * @param view 
  * @param remainseconds 
  */ 
 public void ontickchanged(chronometerview view, long remainseconds); 
 } 
 
 private long mbase; 
 private long mremainseconds; 
 private boolean mstarted; 
 private boolean mrestart; 
 private boolean mvisible; 
 private boolean misenable; 
 
 private ontickchangelistener mticklistener; 
 
 public chronometerview(context context) { 
 this(context, null); 
 } 
 
 public chronometerview(context context, attributeset attrs) { 
 super(context, attrs, 0); 
 } 
 
 public chronometerview(context context, attributeset attrs, int defstyleattr) { 
 super(context, attrs, defstyleattr); 
 updatetext(mremainseconds); 
 } 
 
 @override 
 protected void onwindowvisibilitychanged(int visibility) { 
 super.onwindowvisibilitychanged(visibility); 
 mvisible = visibility == visible; 
 updatestatus(); 
 } 
 
 @override 
 protected void ondetachedfromwindow() { 
 super.ondetachedfromwindow(); 
 mvisible = false; 
 updatestatus(); 
 } 
 
 /** 
 * 启动计时器 
 */ 
 public void start() { 
 if (mrestart && !mstarted) { 
  mremainseconds = mbase; 
 } 
 mstarted = true; 
 updatestatus(); 
 } 
 
 /** 
 * 暂停计时器 
 */ 
 public void pause() { 
 if (mstarted) { 
  mstarted = mrestart = false; 
  updatestatus(); 
 } 
 } 
 
 /** 
 * 停止计时器,再次调用 start()重新启动 
 */ 
 public void stop() { 
 mstarted = false; 
 mrestart = true; 
 updatestatus(); 
 updatetext(mremainseconds = 0); 
 dispatchticklistener(); 
 } 
 
 /** 
 * 刷新内部状态 
 */ 
 private void updatestatus() { 
 boolean isenable = mvisible && mstarted; 
 if (misenable != isenable) { 
  if (isenable) { 
  mhandler.sendmessage(message.obtain(mhandler, tick_what)); 
  } else { 
  mhandler.removemessages(tick_what); 
  } 
  misenable = isenable; 
 } 
 } 
 
 private static final int tick_what = 1; 
 
 private handler mhandler = new handler() { 
 public void handlemessage(android.os.message msg) { 
  if (mremainseconds > 0) { 
  updatetext(--mremainseconds); 
  dispatchticklistener(); 
  sendmessagedelayed(message.obtain(this, tick_what), 1000); 
  } 
 } 
 }; 
 
 private void updatetext(long now) { 
 string text = dateutils.formatelapsedtime(now); 
 settext(text); 
 } 
 
 /** 
 * 在未启动状态下设置开始倒计时时间 
 * 
 * @param baseseconds 
 */ 
 public void setbaseseconds(long baseseconds) { 
 if (baseseconds > 0 && baseseconds != mbase && !mstarted) { 
  mbase = mremainseconds = baseseconds; 
  updatetext(mremainseconds); 
 } 
 } 
 
 /** 
 * 剩余时间 
 * 
 * @return 
 */ 
 public long getremainseconds() { 
 return mremainseconds; 
 } 
 
 public void setontickchangelistener(ontickchangelistener listener) { 
 mticklistener = listener; 
 } 
 
 public ontickchangelistener getticklistener() { 
 return mticklistener; 
 } 
 
 private void dispatchticklistener() { 
 if (mticklistener != null) { 
  mticklistener.ontickchanged(this, getremainseconds()); 
 } 
 } 
 
 @override 
 public void oninitializeaccessibilityevent(accessibilityevent event) { 
 super.oninitializeaccessibilityevent(event); 
 event.setclassname(chronometerview.class.getname()); 
 } 
 
 @override 
 public void oninitializeaccessibilitynodeinfo(accessibilitynodeinfo info) { 
 super.oninitializeaccessibilitynodeinfo(info); 
 info.setclassname(chronometer.class.getname()); 
 } 
}

 二、xml 中没有加入自定义的控件属性,同textview

<linearlayout 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:orientation="horizontal" > 
 
 <com.freedoman.widgets.calendar.chronometerview 
  android:id="@+id/chronometer_view" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_marginleft="5dp" 
  android:background="@drawable/chronometer_view_bg" 
  android:enabled="true" 
  android:text="00:00" /> 
 
 <button 
  android:id="@+id/start_chronometer_view_btn" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_marginleft="5dp" 
  android:text="start" /> 
 
 <button 
  android:id="@+id/pause_chronometer_view_btn" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_marginleft="5dp" 
  android:text="pause" /> 
 
 <button 
  android:id="@+id/stop_chronometer_view_btn" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:layout_marginleft="5dp" 
  android:text="stop" /> 
 </linearlayout> 

三、在activity中做一个简单的测试(可以发送短信验证码的实际应用场景为例)

public class chronometeractivity extends activity { 
 
 private chronometerview mchronometerview; 
 
 @override 
 protected void oncreate(bundle savedinstancestate) { 
 super.oncreate(savedinstancestate); 
 setcontentview(r.layout.activity_clock); 
 
 // 自定义计时器 
 if (mchronometerview == null) { 
  mchronometerview = (chronometerview) findviewbyid(r.id.chronometer_view); 
  mchronometerview.setbaseseconds(60); 
  mchronometerview.setontickchangelistener(new ontickchangelistener() { 
  @override 
  public void ontickchanged(chronometerview view, long curtimemills) { 
   system.out.println(curtimemills); 
   view.setenabled(curtimemills == 0 || curtimemills == 60); 
   if (curtimemills == 0) { 
   mchronometerview.settext("重新发送"); 
   } 
  } 
  }); 
  mchronometerview.settext("点击发送验证码"); 
 } 
 findviewbyid(r.id.start_chronometer_view_btn).setonclicklistener(mclicklistener); 
 findviewbyid(r.id.pause_chronometer_view_btn).setonclicklistener(mclicklistener); 
 findviewbyid(r.id.stop_chronometer_view_btn).setonclicklistener(mclicklistener); 
 } 
 
 private view.onclicklistener mclicklistener = new onclicklistener() { 
 
 @override 
 public void onclick(view v) { 
  switch (v.getid()) { 
 
  case r.id.start_chronometer_view_btn: 
  if (mchronometerview != null) { 
   mchronometerview.start(); 
  } 
  break; 
 
  case r.id.pause_chronometer_view_btn: 
  if (mchronometerview != null) { 
   mchronometerview.pause(); 
  } 
  break; 
 
  case r.id.stop_chronometer_view_btn: 
  if (mchronometerview != null) { 
   mchronometerview.stop(); 
  } 
  break; 
  } 
 } 
 }; 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。