Android 自定義View實(shí)現(xiàn)計(jì)時(shí)文字詳解
前言
在Android開發(fā)中,常常會(huì)有計(jì)時(shí)的一些操作,例如收驗(yàn)證碼的時(shí)候倒計(jì)時(shí),秒表的計(jì)時(shí)等等,于是我就有了一個(gè)寫自定義View的想法,本文效果圖。
那么現(xiàn)在我們將想法換成現(xiàn)實(shí),這個(gè)自定義View比較簡(jiǎn)單,我們來看怎么寫的,首先我們還是在EasyView
中進(jìn)行添加。
一、XML樣式
根據(jù)上面的效果圖,我們首先來確定XML中的屬性樣式,在attrs.xml中增加如下代碼:
<!--計(jì)時(shí)文字--> <declare-styleable name="TimingTextView"> <!--倒計(jì)時(shí)--> <attr name="countdown" format="boolean" /> <!--時(shí)間最大值--> <attr name="max" format="integer" /> <!--時(shí)間單位,時(shí):h,分:m,秒:s--> <attr name="unit"> <enum name="h" value="1" /> <enum name="m" value="2" /> <enum name="s" value="3" /> </attr> </declare-styleable>
這里的計(jì)時(shí)文字目前有3個(gè)屬性,第一個(gè)boolean用來確定是計(jì)時(shí)還是倒計(jì)時(shí),第二個(gè)是最大時(shí)間,第三個(gè)是時(shí)間單位:時(shí)分秒。
二、構(gòu)造方法
之前我說自定義View有三種方式,一種是繼承View,一種是繼承現(xiàn)有的View,還有一種是繼承ViewGroup,那么今天的這個(gè)計(jì)時(shí)文字,我們就可以繼承現(xiàn)有的View,這樣做的目的就是可以讓我們減少一定的工作量,專注于功能上,下面我們?cè)?code>com.llw.easyview包下新建一個(gè)TimingTextView
類,里面的代碼如下所示:
public class TimingTextView extends MaterialTextView { /** * 時(shí)間單位 */ private int mUnit; /** * 計(jì)時(shí)最大值 */ private int mMax; /** * 是否倒計(jì)時(shí) */ private boolean mCountDown; private int mTotal; /** * 是否計(jì)時(shí)中 */ private boolean mTiming; public TimingTextView(Context context) { this(context, null); } public TimingTextView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public TimingTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); @SuppressLint("CustomViewStyleable") TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TimingTextView); mCountDown = typedArray.getBoolean(R.styleable.TimingTextView_countdown, false); mMax = typedArray.getInteger(R.styleable.TimingTextView_max, 60); mUnit = typedArray.getInt(R.styleable.TimingTextView_unit, 3); typedArray.recycle(); } }
因?yàn)橛杏?jì)時(shí)的緣故,所以我們需要一個(gè)計(jì)時(shí)監(jiān)聽,主要用于結(jié)束的時(shí)候進(jìn)行調(diào)用,可以在com.llw.easyview
下新建一個(gè)TimingListener
接口,代碼如下:
public interface TimingListener { void onEnd(); }
三、API方法
下面在TimingTextView中新增一些API方法和變量,首先增加變量:
private TimingListener listener; private CountDownTimer countDownTimer;
然后增加API方法:
/** * 設(shè)置時(shí)間單位 * * @param unit 1,2,3 */ public void setUnit(int unit) { if (unit <= 0 || unit > 3) { throw new IllegalArgumentException("unit value can only be between 1 and 3"); } mUnit = unit; } /** * 設(shè)置最大時(shí)間值 * * @param max 最大值 */ public void setMax(int max) { mMax = max; } /** * 設(shè)置是否為倒計(jì)時(shí) * * @param isCountDown true or false */ public void setCountDown(boolean isCountDown) { mCountDown = isCountDown; } public void setListener(TimingListener listener) { this.listener = listener; } public boolean isTiming() { return mTiming; } /** * 開始 */ public void start() { switch (mUnit) { case 1: mTotal = mMax * 60 * 60 * 1000; break; case 2: mTotal = mMax * 60 * 1000; break; case 3: mTotal = mMax * 1000; break; } if (countDownTimer == null) { countDownTimer = new CountDownTimer(mTotal, 1000) { @Override public void onTick(long millisUntilFinished) { int time = 0; if (mCountDown) { time = (int) (millisUntilFinished / 1000); setText(String.valueOf(time)); } else { time = (int) (mTotal / 1000 - millisUntilFinished / 1000); } setText(String.valueOf(time)); } @Override public void onFinish() { //倒計(jì)時(shí)結(jié)束 end(); } }; mTiming = true; countDownTimer.start(); } } /** * 計(jì)時(shí)結(jié)束 */ public void end() { mTotal = 0; mTiming = false; countDownTimer.cancel(); countDownTimer = null; if (listener != null) { listener.onEnd(); } }
代碼還是很簡(jiǎn)單的,你敢信,這個(gè)自定義View就寫完了,不過可能存在一些問題,我將自定義View的代碼都放到了一個(gè)library下面里,然后將這個(gè)library進(jìn)行構(gòu)建成aar,然后上傳到mavenCentral()
中。
四、使用
然后我們修改一下activity_main.xml,代碼如下所示:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="16dp" tools:context=".MainActivity"> <com.easy.view.MacAddressEditText android:id="@+id/mac_et" android:layout_width="wrap_content" android:layout_height="wrap_content" app:boxBackgroundColor="@color/white" app:boxStrokeColor="@color/black" app:boxStrokeWidth="2dp" app:boxWidth="48dp" app:separator=":" app:textColor="@color/black" app:textSize="16sp" /> <Button android:id="@+id/btn_mac" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="獲取地址" /> <com.easy.view.CircularProgressBar android:id="@+id/cpb_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" app:maxProgress="100" app:progress="10" app:progressbarBackgroundColor="@color/purple_500" app:progressbarColor="@color/purple_200" app:radius="80dp" app:strokeWidth="16dp" app:text="10%" app:textColor="@color/teal_200" app:textSize="28sp" /> <Button android:id="@+id/btn_set_progress" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="隨機(jī)設(shè)置進(jìn)度" /> <com.easy.view.TimingTextView android:id="@+id/tv_timing" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="計(jì)時(shí)文字" android:textColor="@color/black" android:textSize="32sp" app:countdown="false" app:max="60" app:unit="s" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:gravity="center" android:orientation="vertical"> <CheckBox android:id="@+id/cb_flag" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="計(jì)時(shí)" /> <Button android:id="@+id/btn_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="開始" /> </LinearLayout> </LinearLayout>
預(yù)覽效果如下圖所示:
下面我們回到MainActivity中,在onCreate()
方法中添加如下代碼:
//計(jì)時(shí)文本操作 TimingTextView tvTiming = findViewById(R.id.tv_timing); CheckBox cbFlag = findViewById(R.id.cb_flag); Button btnStart = findViewById(R.id.btn_start); tvTiming.setListener(new TimingListener() { @Override public void onEnd() { tvTiming.setText("計(jì)時(shí)文字"); btnStart.setText("開始"); } }); cbFlag.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { cbFlag.setText(isChecked ? "倒計(jì)時(shí)" : "計(jì)時(shí)"); } }); //計(jì)時(shí)按鈕點(diǎn)擊 btnStart.setOnClickListener(v -> { if (tvTiming.isTiming()) { //停止計(jì)時(shí) tvTiming.end(); btnStart.setText("開始"); } else { tvTiming.setMax(6); tvTiming.setCountDown(cbFlag.isChecked()); tvTiming.setUnit(3);//單位 秒 //開始計(jì)時(shí) tvTiming.start(); btnStart.setText("停止"); } });
下面運(yùn)行一下看看:
五、源碼
如果對(duì)你有所幫助的話,不妨 Star 或 Fork,山高水長(zhǎng),后會(huì)有期~
源碼地址:EasyView
以上就是Android 自定義View實(shí)現(xiàn)計(jì)時(shí)文字詳解的詳細(xì)內(nèi)容,更多關(guān)于Android 自定義View計(jì)時(shí)文字的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android?自定義開源庫?EasyView實(shí)現(xiàn)詳解
- Android?TextView冷門實(shí)用方法技巧
- Android?TextView的maxEms和maxLength屬性區(qū)別
- Android報(bào)錯(cuò)Didn‘t?find?class?“android.view.x“問題解決原理剖析
- Android?ViewModel創(chuàng)建不受橫豎屏切換影響原理詳解
- Android源碼解析onResume方法中獲取不到View寬高
- Android設(shè)置TextView樣式SpannableString教程
- Android ViewGroup事件分發(fā)和處理源碼分析
相關(guān)文章
Android重力傳感器實(shí)現(xiàn)滾動(dòng)的彈球
所謂傳感器能夠探測(cè)如光、熱、溫度、重力、方向 等等的功能,本文給大家介紹Android傳感器應(yīng)用之重力傳感器實(shí)現(xiàn)滾動(dòng)的彈球,對(duì)android重力傳感器相關(guān)知識(shí)感興趣的朋友一起看看吧2015-12-12Android實(shí)現(xiàn)類似3D Touch菜單功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)類似3D Touch菜單功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03android獲取當(dāng)前運(yùn)行Activity名字的方法
這篇文章主要介紹了android獲取當(dāng)前運(yùn)行Activity名字的方法,對(duì)比分析了兩種實(shí)現(xiàn)方法供大家選擇,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01Android View移動(dòng)的3種方式總結(jié)
這篇文章主要給大家介紹了Android View移動(dòng)的三種方式,在介紹這三種方式之前先介紹了Android坐標(biāo)系的定義規(guī)則以及View的一些位置參數(shù)。有需要的朋友們可以參考借鑒。2016-09-09Android嵌套滾動(dòng)NestedScroll的實(shí)現(xiàn)了解一下
嵌套滾動(dòng)已經(jīng)算一個(gè)比較常見的特效了,這篇文章主要介紹了Android嵌套滾動(dòng)NestedScroll的實(shí)現(xiàn)了解一下,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06