Android 关于倒计时功能的说说
来源:互联网 发布:网络推广电话营销话术 编辑:程序博客网 时间:2024/06/06 05:04
关于倒计时的实现,可以说有很多的方法,比较常见的就是Timer+TimerTask+Handler了,或者还可以配合Runnable。例如下面的代码:
import java.util.Timer;import java.util.TimerTask;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {Timer timer;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);final TextView tv = (TextView) findViewById(R.id.textView1);Button b = (Button) findViewById(R.id.button1);// 定义Handlerfinal Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//handler处理消息if(msg.what>0){tv1.setText("" + msg.what);}else{//在handler里可以更改UI组件tv.setText("倒时");timer.cancel();}}};b.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {// 定义计时器 timer = new Timer();// 定义计划任务,根据参数的不同可以完成以下种类的工作:在固定时间执行某任务,在固定时间开始重复执行某任务,重复时间间隔可控,在延迟多久后执行某任务,在延迟多久后重复执行某任务,重复时间间隔可控timer.schedule(new TimerTask() {int i = 10;// TimerTask 是个抽象类,实现的是Runable类@Overridepublic void run() {//定义一个消息传过去Message msg = new Message();msg.what = i--;handler.sendMessage(msg);}}, 1000, 200);}});}}
基本逻辑就是这样,需要注意一点是 timer.schedule(task,1000,5000),如果设置为 timer.schedule(task,5000)是不会工作的。因为timer.schedule(task,5000) 是表示执行一次的任务。timer.schedule(task,1000,5000)表示1 秒钟后开始 5 秒钟为周期 的重复执行任务。
这个例子北京简单,下面给出一个完整的例子:
import java.util.Timer;import java.util.TimerTask;import com.example.jishiqi.SaveRun;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {Button btnselecttime, daojishijicubutton;TextView tvTime;private Timer timer = null;private TimerTask task = null;private Handler handler = null;private Message msg = null;float predegree = 0;float secondpredegree = 0;float hourpredegree = 0;int mlCount = -1;@Overridepublic void onCreate(Bundle icicle) {super.onCreate(icicle);setContentView(R.layout.main);btnselecttime = (Button) findViewById(R.id.daojishistartbutton);daojishijicubutton = (Button) findViewById(R.id.daojishijicubutton);tvTime = (TextView) findViewById(R.id.daojishitvTime);SaveRun.setisdaojishi(false);handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1:mlCount--;if (mlCount <= 0) {enddaojishi();}int totalSec = 0;int yushu = 0;totalSec = (int) (mlCount / 10);yushu = (int) (mlCount % 10);int min = (totalSec / 60);int sec = (totalSec % 60);try {tvTime.setText(String.format("%1$02d:%2$02d.%3$d", min,sec, yushu));predegree = (float) (0.6 * mlCount);secondpredegree = (float) (36.0 * mlCount);hourpredegree = (float) (mlCount / 100);} catch (Exception e) {tvTime.setText("" + min + ":" + sec + "." + yushu);e.printStackTrace();}break;default:break;}super.handleMessage(msg);}};}private void enddaojishi() {try {task.cancel();task = null;timer.cancel();timer.purge();timer = null;handler.removeMessages(msg.what);new AlertDialog.Builder(MainActivity.this).setTitle("提示 ").setMessage("倒计时结束").setPositiveButton("确定",new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog,int which) {dialog.cancel();mlCount = 600;btnselecttime.setText("开始");SaveRun.setisdaojishi(false);}}).setCancelable(false).create().show();} catch (Exception e) {e.printStackTrace();}}@Overrideprotected void onStart() {daojishijicubutton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {predegree = 0;secondpredegree = 0;hourpredegree = 0;mlCount = -1;btnselecttime.setText("开始");SaveRun.setisdaojishi(false);try {if (task != null) {task.cancel();task = null;timer.cancel();timer.purge();timer = null;handler.removeMessages(msg.what);}} catch (Exception e) {e.printStackTrace();}}});btnselecttime.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {if (null == timer) {if (mlCount == -1 || mlCount == 0) {mlCount = 600;}if (mlCount > 0) {SaveRun.setisdaojishi(true);btnselecttime.setText("暂停");if (null == task) {task = new TimerTask() {@Overridepublic void run() {if (null == msg) {msg = new Message();} else {msg = Message.obtain();}msg.what = 1;handler.sendMessage(msg);}};}timer = new Timer(true);timer.schedule(task, 100, 100);}} else {try {SaveRun.setisdaojishi(false);btnselecttime.setText("继续");task.cancel();task = null;timer.cancel();timer.purge();timer = null;handler.removeMessages(msg.what);} catch (Exception e) {e.printStackTrace();}}}});super.onStart();}}布局:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/daojishitvTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/daojishibuttonlinear" android:layout_centerInParent="true" android:text="00:00.0" android:textSize="35sp" android:textStyle="bold" /> <LinearLayout android:id="@+id/daojishibuttonlinear" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="74sp" android:background="@drawable/v5_bottom_bar_bg_light" android:orientation="horizontal" > <Button android:id="@+id/daojishistartbutton" android:layout_width="wrap_content" android:layout_height="50sp" android:layout_gravity="center_vertical" android:layout_marginLeft="8sp" android:layout_marginRight="3sp" android:layout_weight="1" android:background="@drawable/startbutton" android:text="开始" /> <Button android:id="@+id/daojishijicubutton" android:layout_width="wrap_content" android:layout_height="50sp" android:layout_gravity="center_vertical" android:layout_marginLeft="3sp" android:layout_marginRight="8sp" android:layout_weight="1" android:background="@drawable/startbutton" android:text="取消" /> </LinearLayout> </LinearLayout></RelativeLayout>
显然,这个方式比较笨拙,我们可以对此进行一个封装,利用Handler和Eunnable,看下面的代码:
package com.example.daojishi;import android.os.Handler;import android.util.Log;public class MyCountDownTimer {private long millisInFuture;private long countDownInterval;private boolean status;public MyCountDownTimer(long pMillisInFuture, long pCountDownInterval) {this.millisInFuture = pMillisInFuture;this.countDownInterval = pCountDownInterval;status = false;Initialize();}public void Stop() {status = false;}public long getCurrentTime() {return millisInFuture;}public void Start() {status = true;}public void Initialize() {final Handler handler = new Handler();Log.v("status", "starting");final Runnable counter = new Runnable() {public void run() {long sec = millisInFuture / 1000;if (status) {if (millisInFuture <= 0) {Log.v("status", "done");} else {Log.v("status", Long.toString(sec) + " seconds remain");millisInFuture -= countDownInterval;handler.postDelayed(this, countDownInterval);}} else {Log.v("status", Long.toString(sec)+ " seconds remain and timer has stopped!");handler.postDelayed(this, countDownInterval);}}};handler.postDelayed(counter, countDownInterval);}}这个类就是负责倒计时的类,下面结合Activity,看一下怎么用:
package com.example.daojishi;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.TextView;public class CounterActivity extends Activity {/** Called when the activity is first created. */TextView timeText;Button startBut;Button stopBut;MyCountDownTimer mycounter;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);timeText = (TextView) findViewById(R.id.time);startBut = (Button) findViewById(R.id.start);stopBut = (Button) findViewById(R.id.stop);mycounter = new MyCountDownTimer(20000, 1000);RefreshTimer();}public void StartTimer(View v) {Log.v("startbutton", "开始倒计时");mycounter.Start();}public void StopTimer(View v) {Log.v("stopbutton", "暂停倒计时");mycounter.Stop();}public void RefreshTimer() {final Handler handler = new Handler();final Runnable counter = new Runnable() {public void run() {timeText.setText(Long.toString(mycounter.getCurrentTime()));handler.postDelayed(this, 100);}};handler.postDelayed(counter, 100);}}布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:weightSum="1" > <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:textAppearance="?android:attr/textAppearanceLarge" > </TextView> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="StartTimer" android:text="Start" > </Button> <Button android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="StopTimer" android:text="Stop" > </Button></LinearLayout>
这样就可以比较方便地使用倒计时功能了。但是还有一个更简单的方法。
在Android中有一个CountDownTimer类,这个类就是用来实现类似倒计时方面的功能。使用的时候,只需要继承自CountDownTimer并实现它的方法。
import android.app.Activity; import android.os.Bundle; import android.content.Intent; import android.os.CountDownTimer; import android.widget.TextView; import android.widget.Toast; public class NewActivity extends Activity { private MyCount mc; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv = (TextView)findViewById(R.id.show); mc = new MyCount(30000, 1000); mc.start(); } /*定义一个倒计时的内部类*/ class MyCount extends CountDownTimer { public MyCount(long millisInFuture, long countDownInterval) { super(millisInFuture, countDownInterval); } @Override public void onFinish() { tv.setText("done"); } @Override public void onTick(long millisUntilFinished) { tv.setText("seconds remaining: " + millisUntilFinished / 1000); } } }onFinish()方法是本次倒计时结束的时候调用的,onTick是每隔1秒钟执行的,我们就是在这里执行重复的任务,像本例子的显示时间。执行完后会自动取消,如果在期间停止的话,可以调用cancel()方法。看一下它的源码就会发现,它是使用Handler+SystemClock来实现的。
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.os;import android.util.Log;/** * Schedule a countdown until a time in the future, with * regular notifications on intervals along the way. * * Example of showing a 30 second countdown in a text field: * * <pre class="prettyprint"> * new CountDownTimer(30000, 1000) { * * public void onTick(long millisUntilFinished) { * mTextField.setText("seconds remaining: " + millisUntilFinished / 1000); * } * * public void onFinish() { * mTextField.setText("done!"); * } * }.start(); * </pre> * * The calls to {@link #onTick(long)} are synchronized to this object so that * one call to {@link #onTick(long)} won't ever occur before the previous * callback is complete. This is only relevant when the implementation of * {@link #onTick(long)} takes an amount of time to execute that is significant * compared to the countdown interval. */public abstract class CountDownTimer { /** * Millis since epoch when alarm should stop. */ private final long mMillisInFuture; /** * The interval in millis that the user receives callbacks */ private final long mCountdownInterval; private long mStopTimeInFuture; /** * @param millisInFuture The number of millis in the future from the call * to {@link #start()} until the countdown is done and {@link #onFinish()} * is called. * @param countDownInterval The interval along the way to receive * {@link #onTick(long)} callbacks. */ public CountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; } /** * Cancel the countdown. */ public final void cancel() { mHandler.removeMessages(MSG); } /** * Start the countdown. */ public synchronized final CountDownTimer start() { if (mMillisInFuture <= 0) { onFinish(); return this; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return this; } /** * Callback fired on regular interval. * @param millisUntilFinished The amount of time until finished. */ public abstract void onTick(long millisUntilFinished); /** * Callback fired when the time is up. */ public abstract void onFinish(); private static final int MSG = 1; // handles counting down private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { synchronized (CountDownTimer.this) { final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { // no tick, just delay until done sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); onTick(millisLeft); // take into account user's onTick taking time to execute long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); // special case: user's onTick took more than interval to // complete, skip to next interval while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay); } } } };}
所以,如果你的程序需要执行一些周期性的任务,就可以考虑使用CountDownTimer这个类了。需要注意的是,在上面的这个例子中,最后显示时间是1,也就是说其实上执行了29次。所以这个地方一定要注意,如果你的任务次数是n,那么设置的时候一定要注意设置成n+1的时间。
最后,欢迎大家评论交流,谢谢。
- Android 关于倒计时功能的说说
- Android倒计时功能的实现
- Android 倒计时功能的实现
- android倒计时功能的实现
- android开发中倒计时功能的实现
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDow…
- android倒计时功能的实现(CountDownTimer)
- Android开发中倒计时功能的实现
- Android倒计时功能的实现(CountDownTimer)
- Android 倒计时功能的实现(CountDownTimer)
- Android开发-03-倒计时功能的实现
- android倒计时功能的实现(CountDownTimer)
- android倒计时功能的实现(CountDownTimer)
- SVN常用命令
- Documentation/dvb/faq.txt
- U-Boot(1) 学习前准备
- oracle SQL 分页查询方法
- sdut——下沉的船
- Android 关于倒计时功能的说说
- 数据结构之直接插入排序
- 链路层常见报文格式及长度
- Vijos P1034家族
- CrtDumpMemoryLeaks报告程序中的内存泄露问题(简单示例代码)
- android多国语言资源命名
- U-Boot(2) 汇编知识学习
- arcengine C# 按行政区范围加载图层数据
- POJ3294--Life Forms