Android自定义Chronometer实现短信验证码秒表倒计时功能
程序员文章站
2024-03-02 19:35:58
本文实例为大家分享了chronometer实现倒计时功能,android提供了实现按照秒计时的api,供大家参考,具体内容如下
一、自定义chronometerview...
本文实例为大家分享了chronometer实现倒计时功能,android提供了实现按照秒计时的api,供大家参考,具体内容如下
一、自定义chronometerview 继续自textview
主要原理:先设置一个基准倒计时时间mbaseseconds,内置handler 每隔1s发送一个空消息,mremainseconds--,同时刷新界面视图,回调给外部调用者,只到为零。外部调用者可通过start()/pause()/stop()来控制计时器的工作状态。
可以app中发送短信验证码的场景为例,做了一个很粗糙的界面,但功能都实现了。
/** * @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; } } }; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。