今天为大家介绍俩种方式,都可以实现倒计时功能。这俩种方式分别是:

  1. Handler+Thread
  2. CountDownTimer

想必大家对于第一种实现方式肯定不会陌生了,简直So easy~那再次回顾下第一种写法~

1.通过使用Handler+Thread实现倒计时
首先编写布局文件

布局文件很简单,就是一个TextView,默认显示Handler获取验证码,点击TextView,进行倒计时操作,完成后恢复默认显示。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_show_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="193dp"
        android:text="Handler获取验证码" />

</RelativeLayout>
放大招,编写Activity,实现效果~
public class MainActivity extends Activity {

    private TextView tvShowH;

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            tvShowH.setText(msg.what - 1 + "s");
            if (msg.what == 0) {
                // 倒计时结束让按钮可用
                tvShowH.setEnabled(true);
                tvShowH.setText("Handler获取验证码");
            }
        }
    };

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

        tvShowH = (TextView) findViewById(R.id.tv_show_h);

        tvShowH.setOnClickListener(listenerH);

    }

    private OnClickListener listenerH = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            tvShowH.setEnabled(false);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 10; i >= 0; i--) {
                        handler.sendEmptyMessage(i);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    };

}

 new CountdownTimer(30000, 1000) {

     public void onTick(long millisUntilFinished) {
         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
     }

     public void onFinish() {
         mTextField.setText("done!");
     }
  }.start();
  那么这俩个方法分别都是什么作用呢?
  3.1 onTick(long millisUntilFinished)
        参数millisUntilFinished是倒计时的剩余时间。在倒计时结束后会调用onFinish。
   3.2 onFinish()
         倒计时结束后需要执行的操作可以写在这里。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_show_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tv_show_h"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="25dp"
        android:text="CountDownTimer获取验证码" />

    <TextView
        android:id="@+id/tv_show_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="178dp"
        android:text="Handler获取验证码" />

</RelativeLayout>
package com.example.hlqcountdowntimer;

import android.app.Activity;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView tvShowH, tvShowC;

    private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            tvShowH.setText(msg.what - 1 + "s");
            if (msg.what == 0) {
                // 倒计时结束让按钮可用
                tvShowH.setEnabled(true);
                tvShowH.setText("Handler获取验证码");
            }
        }
    };

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

        tvShowH = (TextView) findViewById(R.id.tv_show_h);

        tvShowH.setOnClickListener(listenerH);

        tvShowC = (TextView) findViewById(R.id.tv_show_c);

        tvShowC.setOnClickListener(listenerC);

    }

    private OnClickListener listenerH = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            tvShowH.setEnabled(false);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 10; i >= 0; i--) {
                        handler.sendEmptyMessage(i);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    };

    private OnClickListener listenerC = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            tvShowC.setEnabled(false);
            timer.start();
        }
    };

    private CountDownTimer timer = new CountDownTimer(10000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {
            long time = millisUntilFinished / 1000;
            if (time == 0) {
                tvShowC.setText(time + "秒后可重发");
                onFinish();
            }
            tvShowC.setText(time + "秒后可重发");
        }

        @Override
        public void onFinish() {
            tvShowC.setEnabled(true);
            tvShowC.setText("CountDownTimer获取验证码");
        }
    };

}

package com.example.hlqcountdowntimer.weight;

import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.widget.TextView;

public abstract class CountDownTimer {

    private final TextView test;

    /**
     * Millis since epoch when alarm should stop.
     */
    private final long mMillisInFuture;

    /**
     * The interval in millis that the user receives callbacks
     */
    private final long mCountdownInterval;

    private long mStopTimeInFuture;

    /**
     * boolean representing if the timer was cancelled
     */
    private boolean mCancelled = false;

    /**
     * @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 along the way to receive {@link #onTick(long)}
     *            callbacks.
     */
    public CountDownTimer(TextView test, long millisInFuture, long countDownInterval) {
        this.test = test;
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }

    /**
     * Cancel the countdown.
     */
    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

    /**
     * Start the countdown.
     */
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }

    /**
     * Callback fired on regular interval.
     * 
     * @param millisUntilFinished
     *            The amount of time until finished.
     */
    public void onTick(long millisUntilFinished) {
        long time = millisUntilFinished / 1000;
        test.setText(time + "秒后可重发");
    };

    /**
     * Callback fired when the time is up.
     */
    public void onFinish() {
        test.setEnabled(true);
        test.setText("试试吧");
    };

    private static final int MSG = 1;

    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    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 = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
                    while (delay < 0)
                        delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
}