Android實(shí)現(xiàn)一個(gè)倒計(jì)時(shí)自定義控件
(一)前言
Android 其實(shí)提供了一個(gè)倒計(jì)時(shí)控件叫做CountDownTimer,這個(gè)倒計(jì)時(shí)控件用起來也很簡(jiǎn)單,但是要按照我們想要的倒計(jì)時(shí)樣式去做就比較繁瑣了。比如說我們希望倒計(jì)時(shí)按照我們想要的樣式展示HH:MM:SS或者是HH-MM-SS等樣式,或者希望如下展示:
要做的工作就會(huì)比較繁瑣了,不是說不能實(shí)現(xiàn),只是實(shí)現(xiàn)起來代價(jià)比較大,所以如果我們將其做成一個(gè)自定義的view,可以根據(jù)用戶傳進(jìn)來的樣式去做倒計(jì)時(shí)樣式的展示(注:本文的代碼未做這些樣式的功能,但是基于本文代碼很容易實(shí)現(xiàn)這個(gè)功能),下面就一起看看我實(shí)現(xiàn)的倒計(jì)時(shí)自定義控件吧。
(注;本文代碼不可直接使用到項(xiàng)目中,如果需要使用到項(xiàng)目中,還需要對(duì)代碼做處理,比如固定時(shí)間到顯示寬度,不然顯示時(shí)間時(shí)會(huì)出現(xiàn)跳躍和顯示不全對(duì)情況,例如可以測(cè)量“00:00:00”的寬度設(shè)置個(gè)顯示的view,或者讀者可以自己選擇解決的辦法,還有顯示的時(shí)候是否需要去掉字體的內(nèi)邊距,這個(gè)都需要讀者自己去決定,去掉內(nèi)邊距也簡(jiǎn)單,就是TextView的一個(gè)方法setIncludeFontPadding(false)就行了)
(二)效果展示
這個(gè)倒計(jì)時(shí)是精確到了毫秒,但也可以根據(jù)自己的需求去修改。很簡(jiǎn)單將格式從“HH:MM:SS SSS ”改為“HH:MM:SS”就可以了
(三)實(shí)現(xiàn)思路
實(shí)現(xiàn)的思路其實(shí)很簡(jiǎn)單,繼承自一個(gè)TextView,參照系統(tǒng)的倒計(jì)時(shí)控件做一個(gè)封裝就可以了。
首先初始化需要倒計(jì)時(shí)的時(shí)間:
public void init(long timeInFuture, long timeInterval){ mTimeInFuture = timeInFuture; mTimeInterval = timeInterval; mStopTimeInFuture = SystemClock.elapsedRealtime() + mTimeInFuture; updateText(mStopTimeInFuture); }
timeInFuture 表示你要倒計(jì)時(shí)的一個(gè)時(shí)間長(zhǎng)度,比如說10秒,3天,5天等,timeInterval表示時(shí)間間隔,即每次倒計(jì)時(shí)遞減多少時(shí)間,可以是1秒,2秒,3秒…,elapsedRealtime表示獲取從設(shè)備boot后經(jīng)歷的時(shí)間值,通過他加上我們的時(shí)間長(zhǎng)度,就可以準(zhǔn)備開始倒計(jì)時(shí)了。
public void start() { mStarted = true; updateTimer(); }
當(dāng)用戶調(diào)用start()函數(shù)時(shí),會(huì)調(diào)用updateTimer()函數(shù),這個(gè)函數(shù)會(huì)執(zhí)行倒計(jì)時(shí)的邏輯:
private void updateTimer() { boolean running = mVisible && mStarted && isShown(); if(running != mRunning){ if(running) { doCountDownTimer(); }else{ removeCallbacks(mTickRunnable); } mRunning = running; } }
從代碼中可知,只有控件可見并且時(shí)mStarted的情況下才會(huì)去做倒計(jì)時(shí)。倒計(jì)時(shí)的執(zhí)行函數(shù)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); } }
代碼很容易看懂,這個(gè)地方需要特別說明的是,咱們的倒計(jì)時(shí)利用了view的postDelayed方法,lastUpdateTextDuration這個(gè)變量值記錄了上一次更新倒計(jì)時(shí)text所耗費(fèi)的時(shí)間,把這個(gè)時(shí)間考慮上會(huì)讓倒計(jì)時(shí)更加精確,因?yàn)樵赿emo為了演示的需要所以加了兩個(gè)按鈕,在秒殺時(shí),這個(gè)時(shí)間的精確性還是有要求的,如果差異太大的話會(huì)影響用戶體驗(yàn)。
文章開頭說可以讓時(shí)間顯示各種樣式,其實(shí)就是把時(shí)間中的每個(gè)字符分離出來,這樣就能單獨(dú)的定義樣式了:
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]; }
需要加樣式就設(shè)計(jì)好樣式后把分割好的字符填到樣式中就可以了!??!
倒計(jì)時(shí)的邏輯其實(shí)是參照的系統(tǒng)倒計(jì)時(shí)的,這里有個(gè)自定義控件的小技巧,當(dāng)我們接到需求時(shí),先不要忙著去百度,因?yàn)榇蠊竞芏鄷r(shí)候設(shè)計(jì)的控件百度上很難找到的就算找到了可能也不符合要求,還可能會(huì)有隱藏的bug,這時(shí)可以參照Android系統(tǒng)是如何實(shí)現(xiàn)類似的控件的,參照系統(tǒng)的控件做出來的自定義控件,效果和性能會(huì)相對(duì)好一些。先說這么多,有問題歡迎一起討論。
(三)代碼地址
代碼倉(cāng)庫(kù)使用的是國(guó)內(nèi)的gitee,推薦大家使用起來!?。?!
源碼地址
總結(jié)
到此這篇關(guān)于Android實(shí)現(xiàn)一個(gè)倒計(jì)時(shí)自定義控件的文章就介紹到這了,更多相關(guān)Android倒計(jì)時(shí)控件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android實(shí)現(xiàn)圓圈倒計(jì)時(shí)
- Android實(shí)現(xiàn)倒計(jì)時(shí)的方案梳理
- Android?使用flow實(shí)現(xiàn)倒計(jì)時(shí)的方式
- Android自定義View實(shí)現(xiàn)隨機(jī)數(shù)驗(yàn)證碼
- Android自定義驗(yàn)證碼輸入框的方法實(shí)例
- Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框
- Android滑動(dòng)拼圖驗(yàn)證碼控件使用方法詳解
- Android實(shí)現(xiàn)隨機(jī)生成驗(yàn)證碼
- OpenHarmony實(shí)現(xiàn)類Android短信驗(yàn)證碼及倒計(jì)時(shí)流程詳解
相關(guān)文章
Android Studio使用教程(四):Gradle基礎(chǔ)
這篇文章主要介紹了Android Studio使用教程(四):Gradle基礎(chǔ),本文講解了什么是Gradle、安裝Gradle、Gradle 基本概念等內(nèi)容,需要的朋友可以參考下2015-05-05Android 大文件切割與合并的實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 大文件切割與合并,實(shí)現(xiàn)了很多發(fā)文件和視頻的切割,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11Android中制作自定義dialog對(duì)話框的實(shí)例分享
這篇文章主要介紹了Android中制作自定義dialog對(duì)話框的實(shí)例分享,安卓自帶的Dialog顯然不夠用,因而我們要繼承Dialog類來制作自己的對(duì)話框,需要的朋友可以參考下2016-04-04uniapp打包Android的apk(原生APP-云打包)及發(fā)布測(cè)試全過程
uni-app本地打包apk需要提前做非常多的準(zhǔn)備工作,而且可能會(huì)勸退一些開發(fā)者,下面這篇文章主要給大家介紹了關(guān)于uniapp打包Android的apk(原生APP-云打包)及發(fā)布測(cè)試的相關(guān)資料,需要的朋友可以參考下2023-02-02Android?Activity?View加載與繪制流程深入刨析源碼
這篇文章主要介紹了Android?Activity?View的加載與繪制流程源碼分析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08android實(shí)現(xiàn)點(diǎn)擊按鈕切換不同的fragment布局
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)點(diǎn)擊按鈕切換不同的fragment布局,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12Android實(shí)現(xiàn)仿淘寶購(gòu)物車增加和減少商品數(shù)量功能demo示例
這篇文章主要介紹了Android實(shí)現(xiàn)仿淘寶購(gòu)物車增加和減少商品數(shù)量功能,結(jié)合實(shí)例形式分析了Android實(shí)現(xiàn)的淘寶購(gòu)物車商品數(shù)量變換與計(jì)算相關(guān)技巧,需要的朋友可以參考下2016-07-07