Android自定義Chronometer實(shí)現(xiàn)短信驗(yàn)證碼秒表倒計(jì)時功能
本文實(shí)例為大家分享了Chronometer實(shí)現(xiàn)倒計(jì)時功能,Android提供了實(shí)現(xiàn)按照秒計(jì)時的API,供大家參考,具體內(nèi)容如下
一、自定義ChronometerView 繼續(xù)自TextView
主要原理:先設(shè)置一個基準(zhǔn)倒計(jì)時時間mBaseSeconds,內(nèi)置handler 每隔1s發(fā)送一個空消息,mRemainSeconds--,同時刷新界面視圖,回調(diào)給外部調(diào)用者,只到為零。外部調(diào)用者可通過start()/pause()/stop()來控制計(jì)時器的工作狀態(tài)。
可以app中發(fā)送短信驗(yàn)證碼的場景為例,做了一個很粗糙的界面,但功能都實(shí)現(xiàn)了。

/**
* @name 倒計(jì)時器(類似妙表倒數(shù)計(jì)時,支持暫停、停止、重新開始)
* @author Fanjb
* @date 2015年11月6日
*/
public class ChronometerView extends TextView {
/**
* A callback that notifies when the chronometer has decremented on its own.
*
* @author Fanjb
*/
public interface OnTickChangeListener {
/**
* remain seconds changed
*
* @param view
* @param remainSeconds
*/
public void onTickChanged(ChronometerView view, long remainSeconds);
}
private long mBase;
private long mRemainSeconds;
private boolean mStarted;
private boolean mReStart;
private boolean mVisible;
private boolean mIsEnable;
private OnTickChangeListener mTickListener;
public ChronometerView(Context context) {
this(context, null);
}
public ChronometerView(Context context, AttributeSet attrs) {
super(context, attrs, 0);
}
public ChronometerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
updateText(mRemainSeconds);
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
mVisible = visibility == VISIBLE;
updateStatus();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mVisible = false;
updateStatus();
}
/**
* 啟動計(jì)時器
*/
public void start() {
if (mReStart && !mStarted) {
mRemainSeconds = mBase;
}
mStarted = true;
updateStatus();
}
/**
* 暫停計(jì)時器
*/
public void pause() {
if (mStarted) {
mStarted = mReStart = false;
updateStatus();
}
}
/**
* 停止計(jì)時器,再次調(diào)用 start()重新啟動
*/
public void stop() {
mStarted = false;
mReStart = true;
updateStatus();
updateText(mRemainSeconds = 0);
dispatchTickListener();
}
/**
* 刷新內(nèi)部狀態(tài)
*/
private void updateStatus() {
boolean isEnable = mVisible && mStarted;
if (mIsEnable != isEnable) {
if (isEnable) {
mHandler.sendMessage(Message.obtain(mHandler, TICK_WHAT));
} else {
mHandler.removeMessages(TICK_WHAT);
}
mIsEnable = isEnable;
}
}
private static final int TICK_WHAT = 1;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (mRemainSeconds > 0) {
updateText(--mRemainSeconds);
dispatchTickListener();
sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
}
}
};
private void updateText(long now) {
String text = DateUtils.formatElapsedTime(now);
setText(text);
}
/**
* 在未啟動狀態(tài)下設(shè)置開始倒計(jì)時時間
*
* @param baseSeconds
*/
public void setBaseSeconds(long baseSeconds) {
if (baseSeconds > 0 && baseSeconds != mBase && !mStarted) {
mBase = mRemainSeconds = baseSeconds;
updateText(mRemainSeconds);
}
}
/**
* 剩余時間
*
* @return
*/
public long getRemainSeconds() {
return mRemainSeconds;
}
public void setOnTickChangeListener(OnTickChangeListener listener) {
mTickListener = listener;
}
public OnTickChangeListener getTickListener() {
return mTickListener;
}
private void dispatchTickListener() {
if (mTickListener != null) {
mTickListener.onTickChanged(this, getRemainSeconds());
}
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(ChronometerView.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(Chronometer.class.getName());
}
}
二、xml 中沒有加入自定義的控件屬性,同TextView
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <com.freedoman.widgets.calendar.ChronometerView android:id="@+id/chronometer_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:background="@drawable/chronometer_view_bg" android:enabled="true" android:text="00:00" /> <Button android:id="@+id/start_chronometer_view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="Start" /> <Button android:id="@+id/pause_chronometer_view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="Pause" /> <Button android:id="@+id/stop_chronometer_view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="Stop" /> </LinearLayout>
三、在Activity中做一個簡單的測試(可以發(fā)送短信驗(yàn)證碼的實(shí)際應(yīng)用場景為例)
public class ChronometerActivity extends Activity {
private ChronometerView mChronometerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clock);
// 自定義計(jì)時器
if (mChronometerView == null) {
mChronometerView = (ChronometerView) findViewById(R.id.chronometer_view);
mChronometerView.setBaseSeconds(60);
mChronometerView.setOnTickChangeListener(new OnTickChangeListener() {
@Override
public void onTickChanged(ChronometerView view, long curTimeMills) {
System.out.println(curTimeMills);
view.setEnabled(curTimeMills == 0 || curTimeMills == 60);
if (curTimeMills == 0) {
mChronometerView.setText("重新發(fā)送");
}
}
});
mChronometerView.setText("點(diǎn)擊發(fā)送驗(yàn)證碼");
}
findViewById(R.id.start_chronometer_view_btn).setOnClickListener(mClickListener);
findViewById(R.id.pause_chronometer_view_btn).setOnClickListener(mClickListener);
findViewById(R.id.stop_chronometer_view_btn).setOnClickListener(mClickListener);
}
private View.OnClickListener mClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.start_chronometer_view_btn:
if (mChronometerView != null) {
mChronometerView.start();
}
break;
case R.id.pause_chronometer_view_btn:
if (mChronometerView != null) {
mChronometerView.pause();
}
break;
case R.id.stop_chronometer_view_btn:
if (mChronometerView != null) {
mChronometerView.stop();
}
break;
}
}
};
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- OpenHarmony實(shí)現(xiàn)類Android短信驗(yàn)證碼及倒計(jì)時流程詳解
- Android自定義短信倒計(jì)時view流程分析
- Android使用CountDownTimer模擬短信驗(yàn)證倒計(jì)時
- Android使用Kotlin和RxJava 2.×實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時效果
- Android 用RxBinding與RxJava2實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時功能
- Android實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼倒計(jì)時功能示例
- Android短信驗(yàn)證碼倒計(jì)時驗(yàn)證的2種常用方式
- Android開發(fā)之獲取短信驗(yàn)證碼后按鈕背景變化并且出現(xiàn)倒計(jì)時
- Android封裝實(shí)現(xiàn)短信驗(yàn)證碼的獲取倒計(jì)時
相關(guān)文章
Android實(shí)現(xiàn)簡易的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)簡易的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-10-10
Android中實(shí)現(xiàn)可滑動的Tab的3種方式
這篇文章主要介紹了Android中實(shí)現(xiàn)可滑動的Tab的3種方式,需要的朋友可以參考下2014-02-02
android實(shí)現(xiàn)給未簽名的apk簽名方法
下面小編就為大家?guī)硪黄猘ndroid實(shí)現(xiàn)給未簽名的apk簽名方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
Android仿微信進(jìn)度彈出框的實(shí)現(xiàn)方法
最近公司項(xiàng)目需要實(shí)現(xiàn)類似微信進(jìn)度條彈出框效果,其實(shí)現(xiàn)方法并不難,下面給大家介紹下Android仿微信進(jìn)度彈出框的實(shí)現(xiàn)方法,需要的朋友參考下吧2017-01-01
Android 開發(fā)中根據(jù)搜索內(nèi)容實(shí)現(xiàn)TextView中的文字部分加粗
最近遇到一個需求,需要做一個搜索功能。搜索的內(nèi)容需要加粗顯示。實(shí)現(xiàn)方法很簡單,下面通過本文給大家分享Android 開發(fā)中根據(jù)搜索內(nèi)容實(shí)現(xiàn)TextView中的文字部分加粗樣式,非常不錯,需要的朋友參考下2017-03-03
android里TextView加下劃線的幾種方法總結(jié)
下面小編就為大家?guī)硪黄猘ndroid里TextView加下劃線的幾種方法總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10
Android編程實(shí)現(xiàn)只顯示圖片一部分的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)只顯示圖片一部分的方法,涉及Android針對圖片的局部顯示操作技巧,需要的朋友可以參考下2016-10-10

