热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

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

这篇文章主要介绍了Android自定义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

 
 
  
 
 

三、在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; 
  } 
 } 
 }; 
} 

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


推荐阅读
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 本文介绍了Android开发中Intent的基本概念及其在不同Activity之间的数据传递方式,详细展示了如何通过Intent实现Activity间的跳转和数据传输。 ... [详细]
  • 优化 Android 按钮状态下的背景和文本颜色变化
    本文介绍如何通过 Android 的 Selector 实现按钮在不同状态下(如按压)的背景和文本颜色动态变化。我们将详细讲解实现步骤,并提供完整的代码示例。 ... [详细]
  • 本文详细介绍超文本标记语言(HTML)的基本概念与语法结构。HTML是构建网页的核心语言,通过标记标签描述页面内容,帮助开发者创建结构化、语义化的Web页面。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文探讨了在Windows Server 2008环境下配置Tomcat使用80端口时遇到的问题,包括端口被占用、多项目访问失败等,并提供详细的解决方法和配置建议。 ... [详细]
  • 本文详细介绍了Java Web应用程序中的过滤器(Filter)功能,包括其作用、实现方式及配置方法。过滤器可以在请求到达目标资源之前对其进行预处理,并在响应返回给客户端之前进行后处理。 ... [详细]
  • 本文介绍了多个关于JavaScript的书籍资源、实用工具和编程实例,涵盖从入门到进阶的各个阶段,帮助读者全面提升JavaScript编程能力。 ... [详细]
  • 分享一个简化版的Silverlight链接图项目:Link Map Simplified
    本文介绍了一个使用Silverlight开发的可视化工具,主要用于展示和操作复杂的实体关系图(Graph)。该工具在犯罪调查系统中得到了广泛应用,帮助用户直观地获取和理解相关信息。 ... [详细]
  • 探讨如何从数据库中按分组获取最大N条记录的方法,并分享新年祝福。本文提供多种解决方案,适用于不同数据库系统,如MySQL、Oracle等。 ... [详细]
  • 本文介绍了ArcXML配置文件的分类及其在不同服务中的应用,详细解释了地图配置文件的结构和功能,包括其在Image Service、Feature Service以及ArcMap Server中的使用方法。 ... [详细]
  • 本文详细介绍如何利用已搭建的LAMP(Linux、Apache、MySQL、PHP)环境,快速创建一个基于WordPress的内容管理系统(CMS)。WordPress是一款流行的开源博客平台,适用于个人或小型团队使用。 ... [详细]
  • 本文详细介绍了 RosPack 类的功能和用法,探讨了其在 ROS 系统中的重要作用。RosPack 类提供了类似于终端命令 rospack 的功能,能够方便地查询和管理 ROS 包的相关信息。 ... [详细]
author-avatar
lee某某
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有