Android自定義view實(shí)現(xiàn)倒計(jì)時(shí)控件
本文實(shí)例為大家分享了Android自定義view實(shí)現(xiàn)倒計(jì)時(shí)控件的具體代碼,供大家參考,具體內(nèi)容如下


直接上代碼
自定義TextView
文字展示
public class StrokeTextView extends TextView {
private TextView borderText = null;///用于描邊的TextView
private Context mContext;
public StrokeTextView(Context context) {
super(context);
mContext = context;
borderText = new TextView(context);
init();
}
public StrokeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
borderText = new TextView(context, attrs);
init();
}
public StrokeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
borderText = new TextView(context, attrs, defStyle);
init();
}
public void init() {
TextPaint tp1 = borderText.getPaint();
tp1.setStrokeWidth(12); //設(shè)置描邊寬度
tp1.setStyle(Paint.Style.STROKE); //對(duì)文字只描邊
//設(shè)置自定義字體
Typeface fromAsset = Typeface.createFromAsset(mContext.getAssets(), "fonts/Alibaba-PuHuiTi-Heavy.ttf");
borderText.setTypeface(fromAsset, Typeface.ITALIC); //自定義字體 ITALIC斜體
borderText.setTextColor(Color.parseColor("#F46059")); //設(shè)置描邊顏色
borderText.setShadowLayer(3.0F, 2F, 2F, Color.parseColor("#ffd44042")); //設(shè)置陰影效果(投影)
borderText.setGravity(getGravity());
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
super.setLayoutParams(params);
borderText.setLayoutParams(params);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
CharSequence tt = borderText.getText();
//兩個(gè)TextView上的文字必須一致
if (tt == null || !tt.equals(this.getText())) {
borderText.setText(getText());
this.postInvalidate();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
borderText.measure(widthMeasureSpec, heightMeasureSpec);
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
borderText.layout(left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
borderText.draw(canvas);
super.onDraw(canvas);
}
}
xml
<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:background="#F3B243" android:layout_height="match_parent" tools:context=".countdown.TestCountActivity"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <com.xiao.test.countdown.StrokeTextView android:layout_marginTop="100dp" android:id="@+id/tv_test" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/play_advertising_timer_bg" android:paddingLeft="15dp" android:textColor="#FFFFFF" android:textSize="33sp" android:layout_centerHorizontal="true" android:layout_gravity="center" android:gravity="center_vertical" android:textStyle="italic" android:typeface="monospace" tools:ignore="RtlSymmetry" android:paddingStart="15dp" /> </RelativeLayout> </LinearLayout>
倒計(jì)時(shí)幫助類(lèi)
public class CountDownHelper {
private OnCountDownListener onCountDownListener;
private Disposable disposable;
private long remainingTime;
public CountDownHelper(long remainingTime) {
this.remainingTime = remainingTime;
}
/**
* 回收倒計(jì)時(shí)
*/
public void destory() {
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
/**
* 開(kāi)始倒計(jì)時(shí)
*/
public void startCompute() {
Observable.interval(1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
disposable = d;
}
@Override
public void onNext(Long aLong) {
if (onCountDownListener == null) {
return;
}
remainingTime -= 1000;
if (remainingTime > 0) {
int day = (int) (remainingTime / (1000 * 60 * 60 * 24));
int hour = (int) ((remainingTime % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
int minute = (int) ((remainingTime % (1000 * 60 * 60)) / (1000 * 60));
int second = (int) ((remainingTime % (1000 * 60)) / 1000);
String dayStr = day >= 10 ? String.valueOf(day) : "0" + day;
String hourStr = hour >= 10 ? String.valueOf(hour) : "0" + hour;
String minuteStr = minute >= 10 ? String.valueOf(minute) : "0" + minute;
String secondStr = second >= 10 ? String.valueOf(second) : "0" + second;
onCountDownListener.countDown(dayStr, hourStr, minuteStr, secondStr);
if (remainingTime <= 0) {
onCountDownListener.countDownFinish();
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
} else {
onCountDownListener.countDownFinish();
if (disposable != null && !disposable.isDisposed()) {
disposable.dispose();
}
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
/**
* 設(shè)置倒計(jì)時(shí)回調(diào)監(jiān)聽(tīng)
*
* @param onCountDownListener 倒計(jì)時(shí)監(jiān)聽(tīng)
*/
public void setOnCountDownListener(OnCountDownListener onCountDownListener) {
this.onCountDownListener = onCountDownListener;
}
public interface OnCountDownListener {
/**
* 倒計(jì)時(shí)
*
* @param day 天
* @param hour 小時(shí)
* @param minute 分鐘
* @param second 秒
*/
void countDown(String day, String hour, String minute, String second);
/**
* 倒計(jì)時(shí)完成
*/
void countDownFinish();
}
}
TestCountActivity.java
public class TestCountActivity extends AppCompatActivity {
private CountDownHelper mCountDownHelper;
private StrokeTextView mTvTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_count);
mTvTest = findViewById(R.id.tv_test);
//設(shè)置自定義字體
Typeface fromAsset = Typeface.createFromAsset(getAssets(), "fonts/Alibaba-PuHuiTi-Heavy.ttf");
mTvTest.setTypeface(fromAsset, Typeface.ITALIC); //自定義字體 ITALIC斜體
long aLong = 1787;
mCountDownHelper = new CountDownHelper(aLong * 1000);
mCountDownHelper.startCompute();
mCountDownHelper.setOnCountDownListener(new CountDownHelper.OnCountDownListener() {
@SuppressLint("SetTextI18n")
@Override
public void countDown(String day, String hour, String minute, String second) {
mTvTest.setText(hour + ":" + minute + ":" + second);
}
@Override
public void countDownFinish() {
Log.d("", "結(jié)束倒計(jì)時(shí)");
mCountDownHelper.destory();
//延時(shí)跳轉(zhuǎn)
new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
Toast.makeText(TestCountActivity.this, "時(shí)間到了", Toast.LENGTH_SHORT).show();
return false;
}
}).sendEmptyMessageDelayed(0, 10000);//表示延遲10秒發(fā)送任務(wù)
}
});
}
}
引入依賴(lài)
implementation ‘io.reactivex.rxjava2:rxjava:2.0.1' implementation ‘io.reactivex.rxjava2:rxandroid:2.0.1'
歡迎小伙伴們?cè)u(píng)論
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)啟動(dòng)頁(yè)倒計(jì)時(shí)效果
- Android 實(shí)現(xiàn)搶購(gòu)倒計(jì)時(shí)功能的示例
- android實(shí)現(xiàn)倒計(jì)時(shí)動(dòng)態(tài)圈
- android實(shí)現(xiàn)圓環(huán)倒計(jì)時(shí)控件
- android利用handler實(shí)現(xiàn)倒計(jì)時(shí)功能
- 解決Android-RecyclerView列表倒計(jì)時(shí)錯(cuò)亂問(wèn)題
- Android實(shí)現(xiàn)自定義倒計(jì)時(shí)
- Android 倒計(jì)時(shí)控件 CountDownView的實(shí)例代碼詳解
- Android倒計(jì)時(shí)神器(CountDownTimer)
- Android倒計(jì)時(shí)功能的實(shí)現(xiàn)代碼
- Android 簡(jiǎn)單實(shí)現(xiàn)倒計(jì)時(shí)功能
- Android自定義TimeButton實(shí)現(xiàn)倒計(jì)時(shí)按鈕
- Android實(shí)現(xiàn)倒計(jì)時(shí)的按鈕效果
- 利用Android設(shè)計(jì)一個(gè)倒計(jì)時(shí)組件
相關(guān)文章
Android使用surfaceView自定義抽獎(jiǎng)大轉(zhuǎn)盤(pán)
這篇文章主要為大家詳細(xì)介紹了Android使用surfaceView自定義抽獎(jiǎng)大轉(zhuǎn)盤(pán),熟練掌握SurfaceVie實(shí)現(xiàn)抽獎(jiǎng)大轉(zhuǎn)盤(pán),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
Android App開(kāi)發(fā)中創(chuàng)建Fragment組件的教程
這篇文章主要介紹了Android App開(kāi)發(fā)中創(chuàng)建Fragment的教程,Fragment是用以更靈活地構(gòu)建多屏幕界面的可UI組件,需要的朋友可以參考下2016-05-05
TableLayout(表格布局)基礎(chǔ)知識(shí)點(diǎn)詳解
在本文里我們給大家分享了關(guān)于TableLayout(表格布局)的相關(guān)基礎(chǔ)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-02-02
Android基于OkHttp實(shí)現(xiàn)下載和上傳圖片
這篇文章主要為大家詳細(xì)介紹了Android基于OkHttp實(shí)現(xiàn)下載和上傳圖片功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11
揭秘在ListView等AdapterView上動(dòng)態(tài)添加刪除項(xiàng)的陷阱
今天遇到這么個(gè)需求,需要在運(yùn)行時(shí)動(dòng)態(tài)添加ListView的item,看起來(lái)很簡(jiǎn)單,實(shí)際操作過(guò)程中卻遇到了麻煩,下面揭秘在ListView等AdapterView上動(dòng)態(tài)添加刪除項(xiàng)的陷阱2016-04-04
Android開(kāi)發(fā)實(shí)現(xiàn)NFC刷卡讀取的兩種方式
這篇文章主要為大家詳細(xì)介紹了Android開(kāi)發(fā)中實(shí)現(xiàn)NFC刷卡讀取的兩種方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
簡(jiǎn)單實(shí)現(xiàn)Android驗(yàn)證碼
在登錄或者注冊(cè)的時(shí)候要求輸入驗(yàn)證碼,這篇文章主要為大家詳細(xì)介紹了如何簡(jiǎn)單實(shí)現(xiàn)Android驗(yàn)證碼的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12

