Android 关于倒计时功能的实现
关于倒计时的实现,可以说有很多的方法,比较常见的就是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;
- @Override
- public 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);
- // 定义Handler
- final Handler handler = new Handler() {
- @Override
- public 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() {
- @Override
- public void onClick(View arg0) {
- // 定义计时器
- timer = new Timer();
- // 定义计划任务,根据参数的不同可以完成以下种类的工作:在固定时间执行某任务,在固定时间开始重复执行某任务,重复时间间隔可控,在延迟多久后执行某任务,在延迟多久后重复执行某任务,重复时间间隔可控
- timer.schedule(new TimerTask() {
- int i = 10;
- // TimerTask 是个抽象类,实现的是Runable类
- @Override
- public 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;
- @Override
- public 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() {
- @Override
- public 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() {
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.cancel();
- mlCount = 600;
- btnselecttime.setText("开始");
- SaveRun.setisdaojishi(false);
- }
- }).setCancelable(false).create().show();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- protected void onStart() {
- daojishijicubutton.setOnClickListener(new OnClickListener() {
- @Override
- public 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() {
- @Override
- public 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() {
- @Override
- public 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;
- @Override
- public 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 开发 倒计时功能 转载
原文地址:https://www.cnblogs.com/xch-yang/p/7920419.html Android为我们封装好了一个抽象类CountDownTimer,可以实现计时器功能: /* ...
- App启动页倒计时功能
转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6753418.html 示例代码采用 RxJava + RxLifecycle + Data-Binding ...
- java翻译到mono C#实现系列(4) 利用CountDownTimer类实现倒计时功能 mono版
群里的朋友问利用CountDownTimer类实现倒计时功能怎么实现,我就百度了,参考http://blog.csdn.net/qq344429461/article/details/7521361写 ...
- html5 canvas 实现倒计时 功能
function showTime(a) { var b = { id: "showtime", //canvasid x: 60, //中心点坐标 X轴; y: 60, //中心 ...
- 模块:js实现一个倒计时功能
1.给显示内容加样式 <style> #p1{font-size: large; color: red;} </style> 2.客户端页面 <div id=" ...
- Android Studio调试功能使用总结【转】
Android Studio调试功能使用总结[转] 这段时间一直在使用Intellij IDEA, 今天把调试区工具的使用方法记录于此. 先编译好要调试的程序. 1.设置断点 选定要设置断点的代码 ...
- iOS “获取验证码”按钮的倒计时功能
iOS 的倒计时有多种实现细节,Cocoa Touch 为我们提供了 NSTimer 类和 GCD 的dispatch_source_set_timer方法去更加方便的使用计时器.我们也可以很容易的的 ...
- Android 实现闹钟功能
原文地址:Android 实现闹钟功能作者:Android_Learners 一.手机闹钟主要用到了AlarmManager类,AlarmManager类提供了访问系统定时服务的途径,开发人员可以 ...
- android自定义倒计时控件示例
这篇文章主要介绍了Android秒杀倒计时自定义TextView示例,大家参考使用吧 自定义TextView控件TimeTextView代码: 复制代码 代码如下: import android.co ...
随机推荐
- Http请求的 HttpURLConnection 和 HttpClient
HTTP 请求方式: GET和POST的比较 请求包.png 例子.png 响应包.png 例子.png 请求头描述了客户端向服务器发送请求时使用的http协议类型,所使用的编码,以及发送内容的长度, ...
- 【iOS开发之静态库、动态库】
什么是库? 库 就是程序代码的集合, 是共享程序代码的一种方式,库一般分两类:开源库和闭源库.github中共享一般是开源库:闭源库分为:静态库和动态库,闭源库不开放源代码,是经过编译的二进制文件,一 ...
- Js遍历Josn对象(内容对比页实现思路)
更好的遍历Josn的方法,利用jquery的each方法: var arr1 = [ "one", "two", "three", &quo ...
- sqlserver获取当前id的前一条数据和后一条数据
一.条件字段为数值的情况 select * from tb where id=@id; --当前记录 select top 1 * from tb where id>@id order ...
- C# DateTime的ToString()方法的使用
Console.WriteLine("ToShortDateString:" + DateTime.Now.ToShortDateString()); Console.WriteL ...
- HTML&CSS基础学习笔记1.21-语义化标签
语义化标签 “语义化”指的是机器在需要更少的人类干预的情况下能够研究和收集信息,让网页能够被机器理解,最终让人类受益. HTML 标签语义化是让大家直观的认识标签和属性的用途和作用,很明显<hx ...
- Android性能优化学习
工作以来,越来越觉得性能优化的重要性,从技术角度,它甚至成了决定一个app成败的最关键因素.因此,特地花时间去学习专研性能优化的方法. 学习性能优化最便捷的方式便是研读别人有关性能优化的博客,然而网上 ...
- 窗口过程 - Windows程序设计(SDK)006
窗口过程 让编程改变世界 Change the world by program 内容节选: Windows 把这样一个窗口分为了客户区和非客户区,这里边白色的这一大片就是客户区,而这些标题栏.菜单栏 ...
- F#(1)
如果你也会C#,那不妨了解下F#(1):F# 数据类型 简单介绍 F#(与C#一样,念作“F Sharp”)是一种基于.Net框架的强类型.静态类型的函数式编程语言.可以说C#是一门包含函数式编程 ...
- unexpected problem
一个比较有趣的字符串问题,问题描述如下 大体意思就是给定一个字符串s以及一个整数m,找出一个能满足以上三个条件的字符串t的个数对10e9 + 7 取余输出. 第二三条是关键,t.s = s.t 举个例 ...