如何在Android中启动计时器的倒计时功能?

23
cmtr.setText(finalTime);
cmtr.setBase(SystemClock.elapsedRealtime());

timetest = SystemClock.elapsedRealtime();
Log.d("SETTIME: ", ""+timetest);
cmtr.start();

eltime = SystemClock.elapsedRealtime();
Log.d("ELapsed: ", ""+eltime);
注意:我想要按相反的顺序开始我的计时器。比如我设置了一个10秒的计时器,现在我想要从10秒开始倒数到0秒。所以有人可以帮助我得到这个解决方案吗?非常感谢您的帮助。
7个回答

53
您无法实现倒计时功能,Chronometer小部件只能进行计时,这是它特定的设计目的。如果您想要倒计时,请使用CountDownTimer(Android SDK页面包含一个具体的示例,其中TextView被更新)或自行编写解决方案。
这些类只是简单的封装,为了节省您的时间。如果它们不能完全满足您的需求,您应该考虑编写自己的实现,不必感到不适。
【更新】
正如Ronaldo Bahia在评论中添加的那样,自API 24以来,Chronometer通过setCountDown方法实际上提供了此功能。

我也是,这节省了我的时间。 - Ahmed Adel Ismail
使用CountDownTimer的样例是什么? - Douglas Mesquita
@Paul-Jan 你是对的,Chronometer只能计时但有一个小技巧可以实现倒计时。请查看我对这个问题的回答。 - Parth Anjaria
1
实际上它执行了倒计时:https://developer.android.com/reference/android/widget/Chronometer.html#setCountDown(boolean) - Ronaldo Bahia
@RonaldoBahia确实如此,自API级别24发布以来。这是在创建此Q&A条目3年多之后发布的,但可能适用于当前应用程序的使用。 - Paul-Jan
这应该解释如何在完整示例的上下文中使用setCountDown()。它正在倒计时从什么到什么?那会如何显示? - still_dreaming_1

22

你无法使用计时器小部件进行倒计时。请使用下面的 CountDownTimer 示例。在这里,我的倒计时从01:45分钟开始,1秒=1000。

 CountDownTimer cT =  new CountDownTimer(100000, 1000) {

         public void onTick(long millisUntilFinished) {


                 String v = String.format("%02d", millisUntilFinished/60000);
                 int va = (int)( (millisUntilFinished%60000)/1000);
                 textView.setText("seconds remaining: " +v+":"+String.format("%02d",va));
         }

         public void onFinish() {
             textView.setText("done!");
         }
      };
      cT.start();

1
根据您所提到的,它是01:40分钟而不是01:45分钟。 - varun

4

对于那些仍在寻找其他选项和视图的人,我建议使用Chronometer小部件,并将setCountDown(boolean)设置为true。

例如,在您的活动或片段中:

  view_timer.base = SystemClock.elapsedRealtime() + 10000    
  view_timer.start()

在布局 .xml 文件中的小部件:
<Chronometer
            android:id="@+id/view_timer"
            android:countDown="true"
            tools:targetApi="24"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

据我所知,这应该是新的可接受解决方案。 - sanjeev

2

计时器只能正向计数,但我们可以通过这个小技巧来实现反向计数。

chrono.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
            @Override
            public void onChronometerTick(Chronometer arg0) {
                countUp = (SystemClock.elapsedRealtime() - startTime) / 1000;

                if (countUp % 2 == 0) {
                    chronoRecordingImage.setVisibility(View.VISIBLE);
                } else {
                    chronoRecordingImage.setVisibility(View.INVISIBLE);
                }
                int min = (int) (countUp/60);
                int sec = (int) (countUp%60);

                Utility.printMessage(min+":"+sec);
                int newCount = MAX_TIME - (int) countUp;  // MAIN LOGIC
                String asText = String.format("%02d",(newCount / 60)) + ":"
                        + String.format("%02d", (newCount % 60));

                chrono.setText(asText);
                if (countUp > MAX_TIME) {
                    //time complete
                }
            }
        });

2

6
自 API 级别 24 开始,大多数应用目前都不符合其规则。 - Intrications

0
private static int sec = 60*2;  // this is for 2 for min TODO replace your sec

    public void startTimer(final TextView textView ,int sec) {

    CountDownTimer downTimer= new CountDownTimer(1000 * sec, 1000) {

        public void onTick(long millisUntilFinished) {


            String v = String.format("%02d", millisUntilFinished / 60000);
            int va = (int) ((millisUntilFinished % 60000) / 1000);
            textView.setText(v + ":" + String.format("%02d", va));
        }

        public void onFinish() {
            textView.setText("done!");
        }
    };
    downTimer.start();

}

并调用此函数:

startTimer(tvClock,sec);

0
    package com.quanticheart.camera

//
// Created by Jonn Alves on 01/10/22.
//
import android.content.Context
import android.os.CountDownTimer
import android.os.SystemClock
import android.util.AttributeSet
import android.widget.Chronometer

class PauseChronometer @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0,
) : Chronometer(context, attrs, defStyleAttr) {
    private var timeWhenStopped: Long = 0

    override fun start() {
        if (cdMode) {
            if (!cdRunning)
                captureVideoWithDuration(cdSeconds.toInt())
        } else {
            base = SystemClock.elapsedRealtime() - timeWhenStopped
            super.start()
        }
    }

    override fun stop() {
        if (cdMode) {
            cdRunning = false
            cd?.cancel()
        } else {
            super.stop()
            timeWhenStopped = SystemClock.elapsedRealtime() - base
        }
    }

    fun reset() {
        if (cdMode) {
            cd?.cancel()
            cdSeconds = 0L
            cdMode = false
            cdRunning = false
        } else {
            stop()
            base = SystemClock.elapsedRealtime()
            timeWhenStopped = 0
        }
        text = "00:00"
    }

    private var cd: CountDownTimer? = null
    private var cdSeconds = 0L
    private var cdMode = false
    private var cdRunning = false
    private var cdCallback: (() -> Unit)? = null

    fun startCountdown(seconds: Int) {
        cdSeconds = seconds.toLong()
        cdMode = true
        cd = object : CountDownTimer((seconds * 1000).toLong(), 1000) {
            //Sets 10 second remaining
            override fun onTick(millisUntilFinished: Long) {
                cdRunning = true
                cdSeconds = millisUntilFinished / 1000

                var secondsM = (millisUntilFinished / 1000).toInt()

                val hours = secondsM / (60 * 60)
                val tempMint = secondsM - hours * 60 * 60
                val minutes = tempMint / 60
                secondsM = tempMint - minutes * 60

                val t = String.format("%02d", minutes) + ":" + String.format("%02d", secondsM)
                text = t
            }

            override fun onFinish() {
                cdCallback?.let { it() }
                cdSeconds = 0
                cdMode = false
                cdRunning = false
            }
        }.start()
    }

    fun setCountDownFinishCallback(callback: () -> Unit) {
        this.cdCallback = callback
    }

    var currentTime: Long
        get() = if (cdMode) cdSeconds else timeWhenStopped
        set(time) {
            if (cdMode)
                cdSeconds = time
            else {
                timeWhenStopped = time
                base = SystemClock.elapsedRealtime() - timeWhenStopped
            }
        }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接