一个封装好的倒计时控件

这次带来一个倒计时控件,命名为TimingTextView,依然是只有一个文件,复制粘贴即可用。话不多说,上本体:

TimingTextView.java:

public class TimingTextView extends TextView {
    private static final int TIME_START = 0x001;
    private static final int TIME_FINISH = 0x002;
    private static final int TIME_CHANGE = 0x003;
    private static final int TIME_RESET = 0x004;
    private static final int TIMING = 0x005;

    // 中文模式,显示格式为 00小时00分00秒
    public static final int CHINESE = 0x101;

    // 数字模式,显示格式为 00:00:00
    public static final int MATH = 0x102;


    // 显示精确到小时
    public static final int HOUR = 0x201;

    // 显示精确到分
    public static final int MINUTE = 0x202;

    // 显示精确到秒
    public static final int SECOND = 0x203;

    // 当前显示格式
    private int languageMode = MATH;

    // 当前精确位数
    private int timeMode = HOUR;

    // 倒计时模式下的最大时间
    private int maxTime = 60;

    // 当前时间
    private int time;

    // 是否倒计时模式
    private boolean isCountDown = true;

    // 是否自动刷新显示
    private boolean isAutoRefresh = true;

    private TimingThread thread;
    private boolean isTiming;
    private boolean isPausing;

    // 计时回调
    private OnTimingListener listener;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            try {
                switch (msg.what) {
                    case TIME_CHANGE:
                        setText(calculateTime(time));
                        break;
                    case TIME_START:
                        if (listener != null) listener.onStart();
                        break;
                    case TIME_RESET:
                        setText(calculateTime(time));
                        stop();
                        break;
                    case TIME_FINISH:
                        if (listener != null) listener.onFinish();
                        break;
                    case TIMING:
                        if (listener != null) {
                            listener.onTiming(((time / (60 * 60) + "").length() == 1 ? "0" : "") + time / (60 * 60),
                                    ((time % (60 * 60) / 60 + "").length() == 1 ? "0" : "") + time % (60 * 60) / 60,
                                    ((time % 60 + "").length() == 1 ? "0" : "") + time % 60, TimingTextView.this);
                        }
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    public TimingTextView(Context context) {
        this(context, null);
    }

    public TimingTextView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public TimingTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setText(calculateTime(maxTime));
    }

    /**
     * 计算显示的时间
     *
     * @param time 当前时间
     * @return 时间字串
     */
    private String calculateTime(int time) {
        String hour = ((time / (60 * 60) + "").length() == 1 ? "0" : "") + time / (60 * 60);
        String minute = ((time % (60 * 60) / 60 + "").length() == 1 ? "0" : "") + time % (60 * 60) / 60;
        String second = ((time % 60 + "").length() == 1 ? "0" : "") + time % 60;

        return (timeMode == HOUR ? hour : "") + (timeMode == HOUR ? languageMode == CHINESE ? "小时" : ":" : "")
                + (timeMode == HOUR || timeMode == MINUTE ? minute : "") + (timeMode == HOUR || timeMode == MINUTE ? languageMode == CHINESE ? "分" : ":" : "")
                + second + (languageMode == CHINESE ? "秒" : "");
    }

    private void sendMessage(int what, Handler handler) {
        Message message = new Message();
        message.what = what;
        handler.sendMessage(message);
    }

    /**
     * 开始计时
     */
    public void start() {
        if (!isTiming) {
            thread = new TimingThread();
            thread.start();
        }
    }

    /**
     * 暂停计时
     */
    public void pause() {
        isPausing = true;
    }

    /**
     * 继续计时
     */
    public void resume() {
        isPausing = false;
    }

    /**
     * 停止计时
     */
    public void stop() {
        isTiming = false;
        isPausing = false;
    }

    /**
     * 时间重置
     */
    public void reset() {
        time = isCountDown ? maxTime : 0;
        isTiming = true;
        isPausing = false;
        sendMessage(TIME_RESET, handler);
    }

    /**
     * 设置显示格式
     *
     * @param languageMode 模式,可选项:CHINESE、MATH
     */
    public void setLanguageMode(int languageMode) {
        this.languageMode = languageMode;
        setText(calculateTime(isCountDown ? maxTime : 0));
    }

    /**
     * 设置显示精确位数
     *
     * @param timeMode 精确位数,可选项:HOUR、MINUTE、SECOND
     */
    public void setTimeMode(int timeMode) {
        this.timeMode = timeMode;
        setText(calculateTime(isCountDown ? maxTime : 0));
    }

    /**
     * 最大计时时间,只在倒计时模式下有效
     *
     * @param maxTime 最大时间,单位秒
     */
    public void setMaxTime(int maxTime) {
        this.maxTime = maxTime;
        setText(calculateTime(isCountDown ? maxTime : 0));
    }

    /**
     * 设置是否倒计时
     * 设置为false时从零开始往上计时,无计时上限
     *
     * @param isCountDown
     */
    public void setIsCountDown(boolean isCountDown) {
        this.isCountDown = isCountDown;
        setText(calculateTime(isCountDown ? maxTime : 0));
    }

    /**
     * 是否自动刷新显示
     * 设置为false时需要在回调接口里手动更新需要显示的文字
     *
     * @param isAutoRefresh
     */
    public void setIsAutoRefresh(boolean isAutoRefresh) {
        this.isAutoRefresh = isAutoRefresh;
    }

    /**
     * 获取是否正在计时
     *
     * @return
     */
    public boolean isTiming() {
        return isTiming;
    }

    /**
     * 获取计时是否暂停
     *
     * @return
     */
    public boolean isPausing() {
        return isPausing;
    }

    /**
     * 计时回调接口
     */
    public interface OnTimingListener {
        /**
         * 计时过程中回调
         *
         * @param hour     当前小时数
         * @param minute   当前分钟数
         * @param second   当前秒数
         * @param textView 当前控件实体
         */
        void onTiming(String hour, String minute, String second, TextView textView);

        /**
         * 计时开始时回调
         */
        void onStart();

        /**
         * 计时结束时回调,倒计时模式下才有此回调
         */
        void onFinish();
    }

    /**
     * 设置计时回调接口
     * @param listener
     */
    public void setOnTimingListener(OnTimingListener listener) {
        this.listener = listener;
    }

    class TimingThread extends Thread {
        @Override
        public void run() {
            time = isCountDown ? maxTime : 0;
            isTiming = true;
            isPausing = false;
            sendMessage(TIME_START, handler);
            do {
                try {
                    if (isAutoRefresh) {
                        sendMessage(TIME_CHANGE, handler);
                    } else {
                        sendMessage(TIMING, handler);
                    }
                    time = isCountDown ? time - 1 : time + 1;
                    if (time >= 0) sleep(1000);
                    while (isPausing) {
                        sleep(500);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } while (isTiming && (isCountDown ? time >= 0 : true));
            isTiming = false;
            time = 0;
            sendMessage(TIME_FINISH, handler);
        }
    }
}


然后就能用了。上主页面和布局文件:

MainActivity.java:

public class MainActivity extends Activity {
    private Button startButton, stopButton, pauseButton, resumeButton, resetButton;
    private TimingTextView textView;

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

    private void initData() {

    }

    private void initView() {
        startButton = (Button) findViewById(R.id.start_button);
        stopButton = (Button) findViewById(R.id.stop_button);
        pauseButton = (Button) findViewById(R.id.pause_button);
        resumeButton = (Button) findViewById(R.id.resume_button);
        resetButton = (Button) findViewById(R.id.reset_button);
        textView = (TimingTextView) findViewById(R.id.textview);

        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.start();
            }
        });
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.stop();
            }
        });
        pauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.pause();
            }
        });
        resumeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.resume();
            }
        });
        resetButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                textView.reset();
            }
        });
    }
}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <com.min.timingtextview.TimingTextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:textColor="#3F51B5"
        android:textSize="30sp" />

    <Button
        android:id="@+id/start_button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="START" />

    <Button
        android:id="@+id/stop_button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="STOP" />

    <Button
        android:id="@+id/pause_button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="PAUSE" />

    <Button
        android:id="@+id/resume_button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="RESUME" />

    <Button
        android:id="@+id/reset_button"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_margin="10dp"
        android:text="RESET" />

</LinearLayout>

运行看一下效果:

                                                                 

当然控件支持一些参数设置,设置方法在源码里有详细注释,大家可以自己试一试,这里做几个简单示范,添加代码:

textView.setIsCountDown(false);
textView.setLanguageMode(TimingTextView.CHINESE);
再次运行:

                                                                 


如果还需要自定义显示内容的话可以setIsAutoRefresh(false),让内容不自动刷新,然后setOnTimingListener设置回调接口,在onTiming里自行显示想要的内容就好了。


最后附上源码地址:点击打开链接

 

这次的内容就到这里,我们下次再见。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值