自定义倒计时button)
在我们日常开发中经常会遇到点击按钮然后去发送验证并且button上面会显示一个倒计时。这样的需求实现方法很多比如:handler发送延时消息、CountDownTimer,TimerTask等这些方法都可以实现。今天我给大家分享的是利用CountDownTimer+button自定义控件,这样封装的好处是我们使用简单并且可复用性强。
效果图
支持的自定义属性
<declare-styleable name="CountDownButton">
<attr name="countdown_interval" format="float" />
<attr name="countdown_total_time" format="float" />
<attr name="countdown_beforetext" format="string"/>
<attr name="countdown_aftertext" format="string"/>
</declare-styleable>
countdown_interval:配置间隔时间。
countdown_total_time:倒计时的总时间。
countdown_beforetext:未开始计时时显示的文字,默认值:获取验证码
countdown_aftertext:开始计时后显示的文字,默认值:%d秒后重发
代码
package com.yesway.countdwonbutton;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
/**
* @Description 倒计时按钮
* @Author guojingbu
* @Date 2018/11/7
*/
@SuppressLint("AppCompatCustomView")
public class CountDownButton extends Button implements View.OnClickListener {
/**
* 倒计时默认倒计时间间隔
*/
private static final long DEFAULT_COUNTDOWN_INTERVAL = 1000;
/**
* 默认倒计时总时间
*/
private static final long DEFAULT_COUNTDOWN_TOTAL_TIME = 60 * 1000;
/**
* 倒计时默认倒计时间间隔
*/
private static String DEFAULT_COUNTDOWN_BEFORETEXT;
/**
* 默认倒计时总时间
*/
private static String DEFAULT_COUNTDOWN_AFTERTEXT;
private long countDownInterval = DEFAULT_COUNTDOWN_INTERVAL;
private long countDownTotalTime = DEFAULT_COUNTDOWN_TOTAL_TIME;
private CountDownTimer mCountDownTimer;
/**
* 在点击按钮之前按钮所显示的文字,默认是获取验证码
*/
private String beforeText;
/**
* 在开始倒计时之后那个秒数数字之后所要显示的字,默认是秒
*/
private String afterText;
private OnClickListener mOnClickListener;
public CountDownButton(Context context) {
super(context, null);
init(context, null, 0);
}
public CountDownButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public CountDownButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
DEFAULT_COUNTDOWN_BEFORETEXT = context.getResources().getString(R.string.default_countdown_beforetext);
DEFAULT_COUNTDOWN_AFTERTEXT = context.getResources().getString(R.string.default_countdown_aftertext);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CountDownButton, defStyleAttr, 0);
countDownInterval = (long) a.getFloat(R.styleable.CountDownButton_countdown_interval, DEFAULT_COUNTDOWN_INTERVAL);
countDownTotalTime = (long) a.getFloat(R.styleable.CountDownButton_countdown_total_time, DEFAULT_COUNTDOWN_TOTAL_TIME);
beforeText = a.getString(R.styleable.CountDownButton_countdown_beforetext);
afterText = a.getString(R.styleable.CountDownButton_countdown_aftertext);
if (TextUtils.isEmpty(beforeText)) {
beforeText = DEFAULT_COUNTDOWN_BEFORETEXT;
}
if (TextUtils.isEmpty(afterText)) {
afterText = DEFAULT_COUNTDOWN_AFTERTEXT;
}
a.recycle();
setEnabled(true);
setOnClickListener(this);
CountDownButton.this.setText(beforeText);
mCountDownTimer = new CountDownTimer(countDownTotalTime, countDownInterval) {
@Override
public void onTick(long millisUntilFinished) {
// 时间+15毫秒,防止倒计时产生的毫秒差
setEnabled(false);
CountDownButton.this.setText(String.format(afterText, (millisUntilFinished + 15) / 1000));
}
@Override
public void onFinish() {
CountDownButton.this.setEnabled(true);
CountDownButton.this.setText(beforeText);
}
};
}
/**
* 重启按钮状态
*/
public void resetButton() {
CountDownButton.this.setEnabled(true);
CountDownButton.this.setText(beforeText);
if (mCountDownTimer != null) {
mCountDownTimer.cancel();
}
}
@Override
public void setOnClickListener(@Nullable OnClickListener onclickListener) {
if (onclickListener instanceof CountDownButton) {
super.setOnClickListener(onclickListener);
} else {
this.mOnClickListener = onclickListener;
}
}
@Override
public void onClick(View v) {
mCountDownTimer.start();
if (mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
@Override
protected void onDetachedFromWindow() {
resetButton();
super.onDetachedFromWindow();
}
}
这个自定义控件是比较简单的,代码逻辑也比较简单我就不给大家解释了上面都有注释。整体就是把CountDownTimer给封装到一个button控件中,这样实现简单可复用性强。
使用
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:gravity="center"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.yesway.countdwonbutton.CountDownButton
android:id="@+id/countdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/countdown_selector"
android:gravity="center"
app:countdown_interval="1000"
app:countdown_total_time="100000"
app:countdown_beforetext="@string/count_before_text" />
<com.yesway.countdwonbutton.CountDownButton
android:layout_marginTop="20dp"
android:id="@+id/countdown2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
app:countdown_beforetext="@string/count_before_text" />
</LinearLayout>
MainActivity
package com.yesway.countdown;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.yesway.countdwonbutton.CountDownButton;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CountDownButton countDown = findViewById(R.id.countdown);
CountDownButton countDown2 = findViewById(R.id.countdown2);
countDown.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"请求接口",Toast.LENGTH_SHORT).show();
}
});
countDown2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this,"请求接口",Toast.LENGTH_SHORT).show();
}
});
}
}
使用方法和正常的button一样只是多几个自定义属性而已。
以上就是我分享的内容,比较简单希望大家不要喷我,只是提供一个思路而已。