服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义TimeButton实现倒计时按钮

Android自定义TimeButton实现倒计时按钮

2022-11-11 15:25Cory_boyu Android

这篇文章主要为大家详细介绍了Android自定义TimeButton实现倒计时按钮,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

项目需要要实现一个带有倒计时功能的按钮,其效果类似发送验证码之后在按钮上显示倒计时并且将按钮设置为不可用的功能。

为了项目中其他地方能够调用到,便重写了一个继承于Button的TimeButton来实现倒计时功能,并方便调用。

老规矩,上效果图:

Android自定义TimeButton实现倒计时按钮

逻辑也不复杂,直接上代码:

首先新建一个App.class继承于Application

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.xuboyu.myapplication;
 
/**
 * 用于存放倒计时时间
 * @author bnuzlbs-xuboyu 2017/4/5.
 */
import java.util.Map;
 
import android.app.Application;
 
public class App extends Application {
 // 用于存放倒计时时间
 public static Map<String, Long> map;
}

然后编写TimeButton.class继承于Button

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package com.example.xuboyu.myapplication;
 
 
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
 
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
 
/**
 * 倒计时按钮
 * @author bnuzlbs-xuboyu 2017/4/5.
 * 注意把该类的onCreate()onDestroy()和activity的onCreate()onDestroy()同步处理
 */
public class TimeButton extends Button implements OnClickListener {
 private long lenght = 60 * 1000;// 倒计时长度,这里给了默认60秒
 private String textafter = "秒后重新获取~";
 private String textbefore = "点击获取验证码~";
 private int colorafter;
 private int colorbefore;
 private final String TIME = "time";
 private final String CTIME = "ctime";
 private OnClickListener mOnclickListener;
 private Timer t;
 private TimerTask tt;
 private long time;
 Map<String, Long> map = new HashMap<String, Long>();
 
 public TimeButton(Context context) {
 super(context);
 setOnClickListener(this);
 
 }
 
 public TimeButton(Context context, AttributeSet attrs) {
 super(context, attrs);
 setOnClickListener(this);
 }
 
 @SuppressLint("HandlerLeak")
 Handler han = new Handler() {
 public void handleMessage(android.os.Message msg) {
  TimeButton.this.setText(time / 1000 + textafter);
  time -= 1000;
  if (time < 0) {
  TimeButton.this.setEnabled(true);
  TimeButton.this.setText(textbefore);
  clearTimer();
  }
 };
 };
 
 private void initTimer() {
 time = lenght;
 t = new Timer();
 tt = new TimerTask() {
 
  @Override
  public void run() {
  Log.e("xuboyu", time / 1000 + "");
  han.sendEmptyMessage(0x01);//十六进制的数字1
  }
 };
 }
 
 private void clearTimer() {
 if (tt != null) {
  tt.cancel();
  tt = null;
 }
 if (t != null)
  t.cancel();
 t = null;
 }
 
 @Override
 public void setOnClickListener(OnClickListener l) {
 if (l instanceof TimeButton) {
  super.setOnClickListener(l);
 } else
  this.mOnclickListener = l;
 }
 
 @Override
 public void onClick(View v) {
 if (mOnclickListener != null)
  mOnclickListener.onClick(v);
 initTimer();
 this.setText(time / 1000 + textafter);
 this.setEnabled(false);
 t.schedule(tt, 0, 1000);
 // t.scheduleAtFixedRate(task, delay, period);
 }
 
 /**
 * 和activity的onDestroy()方法同步
 */
 public void onDestroy() {
 if (App.map == null)
  App.map = new HashMap<String, Long>();
 App.map.put(TIME, time);
 App.map.put(CTIME, System.currentTimeMillis());
 clearTimer();
 Log.e("xuboyu", "onDestroy");
 }
 
 /**
 * 和activity的onCreate()方法同步
 */
 public void onCreate(Bundle bundle) {
 Log.e("xuboyu:倒计时相关", App.map + "");
 if (App.map == null)
  return;
 if (App.map.size() <= 0)// 这里表示没有上次未完成的计时
  return;
 long time = System.currentTimeMillis() - App.map.get(CTIME)
  - App.map.get(TIME);
 App.map.clear();
 if (time > 0)
  return;
 else {
  initTimer();
  this.time = Math.abs(time);
  t.schedule(tt, 0, 1000);
  this.setText(time + textafter);
  this.setEnabled(false);
 }
 }
 
 /** * 设置计时时候显示的文本 */
 public TimeButton setTextAfter(String text1) {
 this.textafter = text1;
 return this;
 }
 
 /** * 设置点击之前的文本 */
 public TimeButton setTextBefore(String text0) {
 this.textbefore = text0;
 this.setText(textbefore);
 return this;
 }
 
 /**
 * 设置到计时长度
 * @param lenght
 * 时间 默认毫秒
 * @return
 */
 public TimeButton setLenght(long lenght) {
 this.lenght = lenght;
 return this;
 }
}

最后在MainActivity.class中调用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.example.xuboyu.myapplication;
 
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
 
/**
 * 测试主界面
 * @author bnuzlbs-xuboyu 2017/4/5.
 */
public class MainActivity extends Activity implements OnClickListener {
 
 private TimeButton v;
 private TimeButton v2;
 private TimeButton v3;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 v = (TimeButton) findViewById(R.id.button1);
 v.onCreate(savedInstanceState);
 v.setTextAfter("秒后重新排队").setTextBefore("点击开始排队").setLenght(15 * 1000);
 v.setOnClickListener(this);
 
 v2 = (TimeButton) findViewById(R.id.button2);
 v2.onCreate(savedInstanceState);
 v2.setTextAfter("秒后重新验证").setTextBefore("点击发送验证码").setLenght(10 * 1000);
 v2.setOnClickListener(this);
 
 v3 = (TimeButton) findViewById(R.id.button3);
 v3.onCreate(savedInstanceState);
 v3.setTextAfter("秒后重新倒计时").setTextBefore("点击开始倒计时").setLenght(5 * 1000);
 v3.setOnClickListener(this);
 }
 
 @Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 Toast.makeText(MainActivity.this, "这是处理调用者onclicklistnenr",
  Toast.LENGTH_SHORT).show();
 }
 
 @Override
 protected void onDestroy() {
 // TODO Auto-generated method stub
 v.onDestroy();
 v2.onDestroy();
 super.onDestroy();
 }
}

其中绿色按钮是使用了自定义样式的Button,使用起来也很简单

首先在drawable中新建一个样式文件mybutton.xml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
 <solid android:color="#5cbe6c" />
 
 <!-- 设置按钮的四个角为弧形 -->
 <!-- android:radius 弧形的半径 -->
 <corners android:radius="15dip" />
 
 <!-- padding:Button里面的文字与Button边界的间隔 -->
 <padding
 android:bottom="10dp"
 android:left="10dp"
 android:right="10dp"
 android:top="10dp" />
</shape>

然后在定义TimeButton的时候如下:

?
1
android:background="@drawable/mybutton"
?
1
2
3
4
5
6
7
<com.example.xuboyu.myapplication.TimeButton
 android:id="@+id/button2"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text=""
 android:background="@drawable/mybutton"
 android:layout_margin="20dp"/>

那么定义出来的Button样式就为下图:

Android自定义TimeButton实现倒计时按钮

记得在AndroidManifest.xml中的Application添加:

?
1
android:name=".App"
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<application
 android:allowBackup="true"
 android:icon="@mipmap/ic_launcher"
 android:label="@string/app_name"
 android:supportsRtl="true"
 android:theme="@style/AppTheme"
 android:name=".App">
 <activity android:name=".MainActivity" >
  <intent-filter>
  <action android:name="android.intent.action.MAIN" />
 
  <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
 </activity>
</application>

Ps.这个倒计时按钮存在一个问题,对于长时间计时而言,用户可能在计时后退出应用程序,如果用户把我们的APP置于后台,那么OK,我们的倒计时还是可以进行,但是假如用户在退出后把APP进程滑掉,或者使用了其他软件清理后台等等,就会执行OnDestory方法,再次进去APP的时候只能重新建立一个Timer。所以打算的是使用轻量级存储来储存每次退出后的倒计时数据,然后在重新OnCreate的时候为Timer赋值。当然对于短时间的计时,即在用户可接受的等待范围内是完全可以接受的!有Bug也欢迎指出,对于应用进程被销毁时Timer也销毁这个问题假如你有更好的解决方法,也请多指教!

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

原文链接:https://blog.csdn.net/SSBBY/article/details/69258672

延伸 · 阅读

精彩推荐
  • Androidandroid 分辨率适配的方法

    android 分辨率适配的方法

    先和大家分享下,这个方法不能说万能的,但是最起码它解决了分辨率跟密集度的关系,但是也引来一个问题,就是布局会因为图片资源小而失真,本文将详...

    Android教程网3762020-12-21
  • AndroidAndroid手机内存中文件的读写方法小结

    Android手机内存中文件的读写方法小结

    这篇文章主要介绍了Android手机内存中文件的读写方法,实例总结了Android针对文件读写操作的相关技巧,非常具有实用价值,需要的朋友可以参考下...

    沧海一粟10702021-03-17
  • AndroidAndroid编程学习之异步加载图片的方法

    Android编程学习之异步加载图片的方法

    这篇文章主要介绍了Android编程学习之异步加载图片的方法,以实例形式较为详细的分析了Android异步加载图片所涉及的页面布局及功能实现技巧,具有一定参考...

    非著名程序员9272021-04-05
  • AndroidAndroid利用EditText如何实现搜索框详解

    Android利用EditText如何实现搜索框详解

    EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,下面这篇文章主要给大家介绍了关于Android利用EditText如何实现搜索框的相关资料,文中通过...

    Super_North_W6512022-03-08
  • AndroidAndroid编程之代码创建布局实例分析

    Android编程之代码创建布局实例分析

    这篇文章主要介绍了Android编程之代码创建布局的方法,结合实例形式分析了Android通过代码创建布局的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考...

    lee0oo012252021-04-14
  • AndroidAndroid实现通用筛选栏

    Android实现通用筛选栏

    这篇文章主要为大家详细介绍了Android实现通用筛选栏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    冷不冷8972022-11-04
  • AndroidAndroid操作存放在assets文件夹下SQLite数据库的方法

    Android操作存放在assets文件夹下SQLite数据库的方法

    这篇文章主要介绍了Android操作存放在assets文件夹下SQLite数据库的方法,实例分析了Android操作SQLite数据库的相关技巧,需要的朋友可以参考下...

    RobinTang9532021-03-26
  • AndroidAndroid实现图片在屏幕内缩放和移动效果

    Android实现图片在屏幕内缩放和移动效果

    这篇文章主要为大家详细介绍了Android控制图片在屏幕内缩放和移动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    newcboy3922022-09-23