【安卓基础】倒计时按钮封装(验证码倒计时按钮)

验证码按钮在项目的使用频率应该是100%,现在大多数应用都会采用手机号码登陆,通常都会支持发送验证码登陆的功能。

我在项目中也遇到这样的功能,特别在忘记密码的界面,我注意到一点:当发送验证码之后,要60秒之后才能再发,如果退出界面,重新进入同样需要等待时间结束。

其中分析一下流程应该是这样的:

  1. 倒计时按钮点击:发送验证码
  2. 发送验证码成功:禁用按钮 & 倒计时开始
  3. 倒计时结束之后:恢复按钮

针对这种场景进行分析,如果采用继承Button的方式对项目耦合性太强了,以后不需要移除也特别麻烦。所以抽象一个工具类进行对Button自动化设置会更好,以后不需要了可以随时移除然后重新实现逻辑。

既然是倒计时功能,所以项目需要使用到相关的技术,在安卓开发中,我总结了如下几种倒计时方法:

  1. Handler实现倒计时(sendEmptyMessageDelayed方法)
  2. Thread实现倒计时
  3. View.postDelayed()实现倒计时
  4. CountDownTimer实现倒计时

CountDownTimer是安卓专门未倒计时设计的一个类,使用起来也非常方便,所以我也选择它作为实现的基础。他是一个抽象类,使用时需要继承并实现onTick()和onFinish()方法。

/**
 * 构造函数(millisInFuture:倒计时总时间,countDownInterval:触发回调的时间间隔)
 */
public CountDownTimer(long millisInFuture, long countDownInterval)

/**
 * 每次倒计时都会触发回调,millisUntilFinished表示剩余的时间。
 */
public abstract void onTick(long millisUntilFinished);

/**
 * 倒计时结束后回调
 */
public abstract void onFinish();


再想想自己设计这个工具类的具体思想:

  1. autoHandleWhenActivityCreate(Button indicator) :在onCreate()中调用,绑定按钮并初始化。
  2. autoHandleWhenActivityDestroy() :在onDestroy()中调用,因为CountDownTimer本质上是Handler实现的,所以处理不当会造成内存泄漏。
  3. autoHandleRequestStartTimer() :调用此方法会立即开始倒计时,按钮的倒计时文字将会变化。

贴一贴工具类的具体使用方法:

public class ForgetActivity extends AppCompatActivity {
    Button uaSendCode;

    // 第一步:创建静态计时器类(当前界面有效,重复进入倒计时依然继续)
    private static CountDownTimer mCountDown = new CountDownTimer(60, "发送验证码(%s)", "发送验证码", R.drawable.register_bg_send, R.drawable.register_bg_unsend);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.forget_activity_main);

        uaSendCode = findViewById(R.id.uaSendCode);

        // 第二步:绑定按钮
        mCountDown.autoHandleWhenActivityCreate(uaSendCode);
        
        
        uaSendCode.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 注意:启动计时器需要调用下面的方法
                mCountDown.autoHandleRequestStartTimer();
            }
        });
    }
    
    @Override
    protected void onDestroy() {
        super.onDestroy();

        //第三步:释放内部引用,防止内存泄漏
        mCountDown.autoHandleWhenActivityDestroy();
    }
}


下面贴上具体实现的逻辑:

package com.anbang.family.library;

import android.view.View;
import android.widget.Button;

/**
 * 按钮倒计时
 */
public class CountDownTimer extends android.os.CountDownTimer {

    private Button mIndicator;
    private String mCountDownFormatString = "发送验证码(%s)";
    private String mCountDownFinishString = "发送验证码";
    private int mEnableDrawable;
    private int mUnableDrawable;

    private int mSecond;
    private int mCount;

    /**
     * 是否启动过计时器(mCount一开始不为0,所以配合这个标志做判断是否start计时器)
     */
    private boolean mAlreadyStart = false;

    public CountDownTimer(int second, String countDownFormatString, String countDownFinishString, int enableDrawable, int unableDrawable) {
        super((second <= 0 ? 60 : second) * 1000, 1000);
        this.mSecond = second;
        this.mCount = second;
        this.mCountDownFormatString = countDownFormatString;
        this.mCountDownFinishString = countDownFinishString;
        this.mEnableDrawable = enableDrawable;
        this.mUnableDrawable = unableDrawable;
    }

    public int getmCount() {
        return mCount;
    }

    public void autoHandleWhenActivityCreate(Button indicator) {
        this.mIndicator = indicator;

        if (mCount <= 0 || !mAlreadyStart) {
            mIndicator.setEnabled(true);
            mIndicator.setText(mCountDownFinishString);
            mIndicator.setBackgroundResource(mEnableDrawable);
        } else {
            mIndicator.setEnabled(false);
            mIndicator.setBackgroundResource(mUnableDrawable);
            mIndicator.setText(String.format(mCountDownFormatString, mCount));
        }
    }

    public void autoHandleWhenActivityDestroy() {
        mIndicator = null;
    }

    public void autoHandleRequestStartTimer() {
        if (mCount <= 0 || !mAlreadyStart) {
            mAlreadyStart = true;
            mCount = mSecond <= 0 ? 60 : mSecond;
            if (mIndicator != null) {
                unableIndicator(mCount);
            }
            start();
        }
    }

    @Override
    public void onTick(long millisUntilFinished) {
        mCount--;
        unableIndicator((int) (millisUntilFinished / 1000));
    }

    @Override
    public void onFinish() {
        enableIndicator();
    }

    private void unableIndicator(int second) {
        if (mIndicator != null) {
            mIndicator.setEnabled(false);
            mIndicator.setBackgroundResource(mUnableDrawable);
            mIndicator.setText(String.format(mCountDownFormatString, second));
        }
    }

    private void enableIndicator() {
        if (mIndicator != null) {
            mIndicator.setEnabled(true);
            mIndicator.setText(mCountDownFinishString);
            mIndicator.setBackgroundResource(mEnableDrawable);
        }
    }
}

转载于:https://www.cnblogs.com/nicojerry/p/10350409.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值