首頁 > 軟體

Android實現一個倒計時自定義控制元件

2022-02-13 19:00:27

(一)前言

Android 其實提供了一個倒計時控制元件叫做CountDownTimer,這個倒計時控制元件用起來也很簡單,但是要按照我們想要的倒計時樣式去做就比較繁瑣了。比如說我們希望倒計時按照我們想要的樣式展示HH:MM:SS或者是HH-MM-SS等樣式,或者希望如下展示:

要做的工作就會比較繁瑣了,不是說不能實現,只是實現起來代價比較大,所以如果我們將其做成一個自定義的view,可以根據使用者傳進來的樣式去做倒計時樣式的展示(注:本文的程式碼未做這些樣式的功能,但是基於本文程式碼很容易實現這個功能),下面就一起看看我實現的倒計時自定義控制元件吧。
(注;本文程式碼不可直接使用到專案中,如果需要使用到專案中,還需要對程式碼做處理,比如固定時間到顯示寬度,不然顯示時間時會出現跳躍和顯示不全對情況,例如可以測量“00:00:00”的寬度設定個顯示的view,或者讀者可以自己選擇解決的辦法,還有顯示的時候是否需要去掉字型的內邊距,這個都需要讀者自己去決定,去掉內邊距也簡單,就是TextView的一個方法setIncludeFontPadding(false)就行了)
 

(二)效果展示

這個倒計時是精確到了毫秒,但也可以根據自己的需求去修改。很簡單將格式從“HH:MM:SS SSS ”改為“HH:MM:SS”就可以了

(三)實現思路

實現的思路其實很簡單,繼承自一個TextView,參照系統的倒計時控制元件做一個封裝就可以了。
首先初始化需要倒計時的時間:

 public void init(long timeInFuture, long timeInterval){
        mTimeInFuture = timeInFuture;
        mTimeInterval = timeInterval;
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mTimeInFuture;
        updateText(mStopTimeInFuture);
    }

timeInFuture 表示你要倒計時的一個時間長度,比如說10秒,3天,5天等,timeInterval表示時間間隔,即每次倒計時遞減多少時間,可以是1秒,2秒,3秒…,elapsedRealtime表示獲取從裝置boot後經歷的時間值,通過他加上我們的時間長度,就可以準備開始倒計時了。

  public  void start() {
        mStarted = true;
        updateTimer();
    }

當用戶呼叫start()函數時,會呼叫updateTimer()函數,這個函數會執行倒計時的邏輯:

private void updateTimer() {
        boolean running = mVisible && mStarted && isShown();
        if(running != mRunning){
            if(running) {
                doCountDownTimer();
            }else{
                removeCallbacks(mTickRunnable);
            }
            mRunning = running;
        }

    }

從程式碼中可知,只有控制元件可見並且時mStarted的情況下才會去做倒計時。倒計時的執行函數doCountDownTimer如下:

 private void doCountDownTimer() {
        final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
        if(millisLeft <= 0){
            onFinish();
        }else{
            long lastUpdateTextStart = SystemClock.elapsedRealtime();
            updateText(millisLeft);
            // take into account updateText() take time to execute
            long lastUpdateTextDuration = SystemClock.elapsedRealtime() - lastUpdateTextStart;
            long delay;

            if(millisLeft < mTimeInterval){
                delay = millisLeft - lastUpdateTextDuration;

                if(delay < 0) {
                    delay = 0;
                }
            } else {
                delay = mTimeInterval - lastUpdateTextDuration;
                while (delay < 0) {
                    delay += mTimeInterval;
                }
            }
            postDelayed(mTickRunnable,delay);
        }
    }

程式碼很容易看懂,這個地方需要特別說明的是,咱們的倒計時利用了view的postDelayed方法,lastUpdateTextDuration這個變數值記錄了上一次更新倒計時text所耗費的時間,把這個時間考慮上會讓倒計時更加精確,因為在demo為了演示的需要所以加了兩個按鈕,在秒殺時,這個時間的精確性還是有要求的,如果差異太大的話會影響使用者體驗。

文章開頭說可以讓時間顯示各種樣式,其實就是把時間中的每個字元分離出來,這樣就能單獨的定義樣式了:

 private String formatTime(long now) {
        String split = " : ";
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS", Locale.CHINA);
        String time = sdf.format(now).replace(" ",":");
        Log.d(TAG,"zhongxj: " + time);
        String[] time_arr = time.split(":");
        int hour = Integer.parseInt(time_arr[0]);
        Log.d(TAG,"zhongxj: before transform " + hour);
        hour-=8;
        Log.d(TAG,"zhongxj: " + hour);
        if(hour<10){
            time_arr[0] = "0"+hour;
        }else{
            time_arr[0] = "" + hour;
        }

        return time_arr[0] + split + time_arr[1] + split
                +time_arr[2] + split + time_arr[3];
    }

需要加樣式就設計好樣式後把分割好的字元填到樣式中就可以了!!!

倒計時的邏輯其實是參照的系統倒計時的,這裡有個自定義控制元件的小技巧,當我們接到需求時,先不要忙著去百度,因為大公司很多時候設計的控制元件百度上很難找到的就算找到了可能也不符合要求,還可能會有隱藏的bug,這時可以參照Android系統是如何實現類似的控制元件的,參照系統的控制元件做出來的自定義控制元件,效果和效能會相對好一些。先說這麼多,有問題歡迎一起討論。

(三)程式碼地址

程式碼倉庫使用的是國內的gitee,推薦大家使用起來!!!!
原始碼地址

總結

到此這篇關於Android實現一個倒計時自定義控制元件的文章就介紹到這了,更多相關Android倒計時控制元件內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com