Android控件之一种不需要定时器的倒计时实现方案

213 阅读2分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

简介

Android倒计时的实现方案很多,但是大多数都是使用Handler或者Timer等定时器实现倒计时,实现起来有些复杂,今天介绍一种不需要使用任何定时工具就能实现一种直播倒计时的方案。

一般直播软件在开播前都会有一个 3,2,1 的倒计时准备时间。如下图所示。

实现方案

  1. 倒计时实现

核心原理:本方案使用自定义LiveStartCountdownTextView继承自TextView,注册addTextChangedListener监听,实现TextWatcher接口的三个方法:beforeTextChanged,onTextChanged,afterTextChanged。 当TextView的内容发生变化后,会主动触发addTextChangedListener监听。执行TextWatcher接口的三个方法。 首先我们设置默认初始数字为time = 4,定义一个start方法,调用start方法时,执行 time -=1和 setText(time.toString()),此时LiveStartCountdownTextView的内容发生改变为3,触发addTextChangedListener监听。然后在afterTextChanged方法中执行数字改变的操作。

public interface TextWatcher extends NoCopySpan {
    void beforeTextChanged(CharSequence var1, int var2, int var3, int var4);

    void onTextChanged(CharSequence var1, int var2, int var3, int var4);

    void afterTextChanged(Editable var1);
}
  1. 动画添加

倒计时一般间隔为1秒,同时具有缩放动画,文字先变大再缩小。这里使用的是属性动画,时间间隔为500毫秒。

放大动画:

val enterFloatArray = floatArrayOf( 0f,0.4f, 0.6f, 0.8f, 1.0f, 1.0f, 1.0f, 1.0f)
                enterAnimation = ValueAnimator.ofFloat(*enterFloatArray)
                enterAnimation?.duration = 500L //设置时间间隔
                enterAnimation?.interpolator = DecelerateInterpolator() //设置插值器
                enterAnimation?.addUpdateListener {
                    val value = it.animatedValue
                    //设置文字缩放
                    this@LiveStartCountdownTextView.scaleX = (value as Float)
                    this@LiveStartCountdownTextView.scaleY = (value as Float)
                }
                enterAnimation?.addListener(object :Animator.AnimatorListener{
                    override fun onAnimationStart(animation: Animator?) {

                    }

                    override fun onAnimationEnd(animation: Animator?) {
                        //方法结束后,缩小
                        outAnimation?.start()
                    }

                    override fun onAnimationCancel(animation: Animator?) {

                    }

                    override fun onAnimationRepeat(animation: Animator?) {

                    }

                })
                enterAnimation?.start()

缩小动画:

  outAnimation = ValueAnimator.ofFloat(1.0f, 0.8f, 0.6f, 0.4f, 0f, 0f, 0f, 0f, 0f)
                outAnimation?.duration = 500L
                outAnimation?.interpolator = DecelerateInterpolator()
                outAnimation?.addUpdateListener {
                    val values = it.animatedValue
                    this@LiveStartCountdownTextView.scaleX = (values as Float)
                    this@LiveStartCountdownTextView.scaleY = (values as Float)
                }
                outAnimation?.addListener(object :Animator.AnimatorListener{
                    override fun onAnimationStart(animation: Animator?) {

                    }

                    override fun onAnimationEnd(animation: Animator?) {
                        //动画执行完结束后取消
                        outAnimation?.cancel()
                        //如果当前显示的time>1 继续执行
                        if (time > 1 && playing) {
                            startAnimal()
                        } else {
                            //结束回调
                            if (mCountdownListener != null && playing) mCountdownListener?.onEnd()
                        }
                    }

                    override fun onAnimationCancel(animation: Animator?) {

                    }

                    override fun onAnimationRepeat(animation: Animator?) {

                    }

                })
总结:使用TextView原生监听addTextChangedListener实现倒计时功能,代码简洁,实现简单。