Android: How to pause and resume a Count Down Timer?

后端 未结 8 1635
长发绾君心
长发绾君心 2020-12-02 17:20

I have developed a Count Down Timer and I am not sure how to pause and resume the timer as the textview for the timer is being clicked. Click to start then click again to pa

8条回答
  •  旧时难觅i
    2020-12-02 17:49

    /*
     * Copyright (C) 2010 Andrew Gainer
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    // Adapted from Android's CountDownTimer class
    
    package com.cycleindex.multitimer;
    
    import android.os.Handler;
    import android.os.Message;
    import android.os.SystemClock;
    
    /**
     * Schedule a countdown until a time in the future, with
     * regular notifications on intervals along the way.
     *
      * The calls to {@link #onTick(long)} are synchronized to this object so that
     * one call to {@link #onTick(long)} won't ever occur before the previous
     * callback is complete.  This is only relevant when the implementation of
     * {@link #onTick(long)} takes an amount of time to execute that is significant
     * compared to the countdown interval.
     */
    public abstract class CountDownTimerWithPause {
    
        /**
         * Millis since boot when alarm should stop.
         */
      private long mStopTimeInFuture;
    
      /**
       * Real time remaining until timer completes
       */
        private long mMillisInFuture;
    
        /**
         * Total time on timer at start
         */
        private final long mTotalCountdown;
    
        /**
         * The interval in millis that the user receives callbacks
         */
        private final long mCountdownInterval;
    
        /**
         * The time remaining on the timer when it was paused, if it is currently paused; 0 otherwise.
         */
        private long mPauseTimeRemaining;
    
        /**
         * True if timer was started running, false if not.
         */
        private boolean mRunAtStart;
    
        /**
         * @param millisInFuture The number of millis in the future from the call
         *   to {@link #start} until the countdown is done and {@link #onFinish()}
         *   is called
         * @param countDownInterval The interval in millis at which to execute
         *   {@link #onTick(millisUntilFinished)} callbacks
         * @param runAtStart True if timer should start running, false if not
         */
        public CountDownTimerWithPause(long millisOnTimer, long countDownInterval, boolean runAtStart) {
            mMillisInFuture = millisOnTimer;
            mTotalCountdown = mMillisInFuture;
            mCountdownInterval = countDownInterval;
            mRunAtStart = runAtStart;
        }
    
        /**
         * Cancel the countdown and clears all remaining messages
         */
        public final void cancel() {
            mHandler.removeMessages(MSG);
        }
    
        /**
         * Create the timer object.
         */
        public synchronized final CountDownTimerWithPause create() {
            if (mMillisInFuture <= 0) {
                onFinish();
            } else {
              mPauseTimeRemaining = mMillisInFuture;
            }
    
            if (mRunAtStart) {
              resume();
            }
    
            return this;
        }
    
        /**
         * Pauses the counter.
         */
      public void pause () {
        if (isRunning()) {
          mPauseTimeRemaining = timeLeft();
          cancel();
        }
      }
    
      /**
       * Resumes the counter.
       */
      public void resume () {
        if (isPaused()) {
          mMillisInFuture = mPauseTimeRemaining;
          mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
              mHandler.sendMessage(mHandler.obtainMessage(MSG));
          mPauseTimeRemaining = 0;
        }
      }
    
      /**
       * Tests whether the timer is paused.
       * @return true if the timer is currently paused, false otherwise.
       */
      public boolean isPaused () {
        return (mPauseTimeRemaining > 0);
      }
    
      /**
       * Tests whether the timer is running. (Performs logical negation on {@link #isPaused()})
       * @return true if the timer is currently running, false otherwise.
       */
      public boolean isRunning() {
        return (! isPaused());
      }
    
      /**
       * Returns the number of milliseconds remaining until the timer is finished
       * @return number of milliseconds remaining until the timer is finished
       */
      public long timeLeft() {
        long millisUntilFinished;
        if (isPaused()) {
          millisUntilFinished = mPauseTimeRemaining;
        } else {
          millisUntilFinished = mStopTimeInFuture - SystemClock.elapsedRealtime();
          if (millisUntilFinished < 0) millisUntilFinished = 0;
        }
        return millisUntilFinished;
      }
    
      /**
       * Returns the number of milliseconds in total that the timer was set to run
       * @return number of milliseconds timer was set to run
       */
      public long totalCountdown() {
        return mTotalCountdown;
      }
    
      /**
       * Returns the number of milliseconds that have elapsed on the timer.
       * @return the number of milliseconds that have elapsed on the timer.
       */
      public long timePassed() {
        return mTotalCountdown - timeLeft();
      }
    
      /**
       * Returns true if the timer has been started, false otherwise.
       * @return true if the timer has been started, false otherwise.
       */
      public boolean hasBeenStarted() {
        return (mPauseTimeRemaining <= mMillisInFuture);
      }
    
        /**
         * Callback fired on regular interval
         * @param millisUntilFinished The amount of time until finished
         */
        public abstract void onTick(long millisUntilFinished);
    
        /**
         * Callback fired when the time is up.
         */
        public abstract void onFinish();
    
    
        private static final int MSG = 1;
    
    
        // handles counting down
        private Handler mHandler = new Handler() {
    
            @Override
            public void handleMessage(Message msg) {
    
                synchronized (CountDownTimerWithPause.this) {
                    long millisLeft = timeLeft();
    
                    if (millisLeft <= 0) {
                        cancel();
                      onFinish();
                    } else if (millisLeft < mCountdownInterval) {
                        // no tick, just delay until done
                        sendMessageDelayed(obtainMessage(MSG), millisLeft);
                    } else {
                        long lastTickStart = SystemClock.elapsedRealtime();
                        onTick(millisLeft);
    
                        // take into account user's onTick taking time to execute
                        long delay = mCountdownInterval - (SystemClock.elapsedRealtime() - lastTickStart);
    
                        // special case: user's onTick took more than mCountdownInterval to
                        // complete, skip to next interval
                        while (delay < 0) delay += mCountdownInterval;
    
                        sendMessageDelayed(obtainMessage(MSG), delay);
                    }
                }
            }
        };
    }
    

    Source : This Gist.

提交回复
热议问题