Android 关于倒计时功能的说说

关于倒计时的实现,可以说有很多的方法,比较常见的就是Timer+TimerTask+Handler了,或者还可以配合Runnable。例如下面的代码:

[html] view plaincopy

  1. import java.util.Timer;
  2. import java.util.TimerTask;
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.os.Handler;
  6. import android.os.Message;
  7. import android.util.Log;
  8. import android.view.View;
  9. import android.widget.Button;
  10. import android.widget.TextView;
  11. public class MainActivity extends Activity {
  12. Timer timer;
  13. @Override
  14. public void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.main);
  17. final TextView tv = (TextView) findViewById(R.id.textView1);
  18. Button b = (Button) findViewById(R.id.button1);
  19. // 定义Handler
  20. final Handler handler = new Handler() {
  21. @Override
  22. public void handleMessage(Message msg) {
  23. super.handleMessage(msg);
  24. //handler处理消息
  25. if(msg.what>0){
  26. tv1.setText("" + msg.what);
  27. }else{
  28. //在handler里可以更改UI组件
  29. tv.setText("倒时");
  30. timer.cancel();
  31. }
  32. }
  33. };
  34. b.setOnClickListener(new View.OnClickListener() {
  35. @Override
  36. public void onClick(View arg0) {
  37. // 定义计时器
  38. timer = new Timer();
  39. // 定义计划任务,根据参数的不同可以完成以下种类的工作:在固定时间执行某任务,在固定时间开始重复执行某任务,重复时间间隔可控,在延迟多久后执行某任务,在延迟多久后重复执行某任务,重复时间间隔可控
  40. timer.schedule(new TimerTask() {
  41. int i = 10;
  42. // TimerTask 是个抽象类,实现的是Runable类
  43. @Override
  44. public void run() {
  45. //定义一个消息传过去
  46. Message msg = new Message();
  47. msg.what = i--;
  48. handler.sendMessage(msg);
  49. }
  50. }, 1000, 200);
  51. }
  52. });
  53. }
  54. }

基本逻辑就是这样,需要注意一点是 timer.schedule(task,1000,5000),如果设置为 timer.schedule(task,5000)是不会工作的。因为timer.schedule(task,5000) 是表示执行一次的任务。timer.schedule(task,1000,5000)表示1 秒钟后开始 5 秒钟为周期 的重复执行任务。

这个例子北京简单,下面给出一个完整的例子:

[html] view plaincopy

  1. import java.util.Timer;
  2. import java.util.TimerTask;
  3. import com.example.jishiqi.SaveRun;
  4. import android.app.Activity;
  5. import android.app.AlertDialog;
  6. import android.content.DialogInterface;
  7. import android.os.Bundle;
  8. import android.os.Handler;
  9. import android.os.Message;
  10. import android.view.View;
  11. import android.view.View.OnClickListener;
  12. import android.widget.Button;
  13. import android.widget.TextView;
  14. public class MainActivity extends Activity {
  15. Button btnselecttime, daojishijicubutton;
  16. TextView tvTime;
  17. private Timer timer = null;
  18. private TimerTask task = null;
  19. private Handler handler = null;
  20. private Message msg = null;
  21. float predegree = 0;
  22. float secondpredegree = 0;
  23. float hourpredegree = 0;
  24. int mlCount = -1;
  25. @Override
  26. public void onCreate(Bundle icicle) {
  27. super.onCreate(icicle);
  28. setContentView(R.layout.main);
  29. btnselecttime = (Button) findViewById(R.id.daojishistartbutton);
  30. daojishijicubutton = (Button) findViewById(R.id.daojishijicubutton);
  31. tvTime = (TextView) findViewById(R.id.daojishitvTime);
  32. SaveRun.setisdaojishi(false);
  33. handler = new Handler() {
  34. @Override
  35. public void handleMessage(Message msg) {
  36. switch (msg.what) {
  37. case 1:
  38. mlCount--;
  39. if (mlCount <= 0) {
  40. enddaojishi();
  41. }
  42. int totalSec = 0;
  43. int yushu = 0;
  44. totalSec = (int) (mlCount / 10);
  45. yushu = (int) (mlCount % 10);
  46. int min = (totalSec / 60);
  47. int sec = (totalSec % 60);
  48. try {
  49. tvTime.setText(String.format("%1$02d:%2$02d.%3$d", min,
  50. sec, yushu));
  51. predegree = (float) (0.6 * mlCount);
  52. secondpredegree = (float) (36.0 * mlCount);
  53. hourpredegree = (float) (mlCount / 100);
  54. } catch (Exception e) {
  55. tvTime.setText("" + min + ":" + sec + "." + yushu);
  56. e.printStackTrace();
  57. }
  58. break;
  59. default:
  60. break;
  61. }
  62. super.handleMessage(msg);
  63. }
  64. };
  65. }
  66. private void enddaojishi() {
  67. try {
  68. task.cancel();
  69. task = null;
  70. timer.cancel();
  71. timer.purge();
  72. timer = null;
  73. handler.removeMessages(msg.what);
  74. new AlertDialog.Builder(MainActivity.this)
  75. .setTitle("提示 ")
  76. .setMessage("倒计时结束")
  77. .setPositiveButton("确定",
  78. new DialogInterface.OnClickListener() {
  79. @Override
  80. public void onClick(DialogInterface dialog,
  81. int which) {
  82. dialog.cancel();
  83. mlCount = 600;
  84. btnselecttime.setText("开始");
  85. SaveRun.setisdaojishi(false);
  86. }
  87. }).setCancelable(false).create().show();
  88. } catch (Exception e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. @Override
  93. protected void onStart() {
  94. daojishijicubutton.setOnClickListener(new OnClickListener() {
  95. @Override
  96. public void onClick(View v) {
  97. predegree = 0;
  98. secondpredegree = 0;
  99. hourpredegree = 0;
  100. mlCount = -1;
  101. btnselecttime.setText("开始");
  102. SaveRun.setisdaojishi(false);
  103. try {
  104. if (task != null) {
  105. task.cancel();
  106. task = null;
  107. timer.cancel();
  108. timer.purge();
  109. timer = null;
  110. handler.removeMessages(msg.what);
  111. }
  112. } catch (Exception e) {
  113. e.printStackTrace();
  114. }
  115. }
  116. });
  117. btnselecttime.setOnClickListener(new OnClickListener() {
  118. @Override
  119. public void onClick(View arg0) {
  120. if (null == timer) {
  121. if (mlCount == -1 || mlCount == 0) {
  122. mlCount = 600;
  123. }
  124. if (mlCount > 0) {
  125. SaveRun.setisdaojishi(true);
  126. btnselecttime.setText("暂停");
  127. if (null == task) {
  128. task = new TimerTask() {
  129. @Override
  130. public void run() {
  131. if (null == msg) {
  132. msg = new Message();
  133. } else {
  134. msg = Message.obtain();
  135. }
  136. msg.what = 1;
  137. handler.sendMessage(msg);
  138. }
  139. };
  140. }
  141. timer = new Timer(true);
  142. timer.schedule(task, 100, 100);
  143. }
  144. } else {
  145. try {
  146. SaveRun.setisdaojishi(false);
  147. btnselecttime.setText("继续");
  148. task.cancel();
  149. task = null;
  150. timer.cancel();
  151. timer.purge();
  152. timer = null;
  153. handler.removeMessages(msg.what);
  154. } catch (Exception e) {
  155. e.printStackTrace();
  156. }
  157. }
  158. }
  159. });
  160. super.onStart();
  161. }
  162. }

布局:

[html] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <TextView
  7. android:id="@+id/daojishitvTime"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_above="@+id/daojishibuttonlinear"
  11. android:layout_centerInParent="true"
  12. android:text="00:00.0"
  13. android:textSize="35sp"
  14. android:textStyle="bold" />
  15. <LinearLayout
  16. android:id="@+id/daojishibuttonlinear"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:layout_alignParentBottom="true"
  20. android:orientation="vertical" >
  21. <LinearLayout
  22. android:layout_width="match_parent"
  23. android:layout_height="74sp"
  24. android:background="@drawable/v5_bottom_bar_bg_light"
  25. android:orientation="horizontal" >
  26. <Button
  27. android:id="@+id/daojishistartbutton"
  28. android:layout_width="wrap_content"
  29. android:layout_height="50sp"
  30. android:layout_gravity="center_vertical"
  31. android:layout_marginLeft="8sp"
  32. android:layout_marginRight="3sp"
  33. android:layout_weight="1"
  34. android:background="@drawable/startbutton"
  35. android:text="开始" />
  36. <Button
  37. android:id="@+id/daojishijicubutton"
  38. android:layout_width="wrap_content"
  39. android:layout_height="50sp"
  40. android:layout_gravity="center_vertical"
  41. android:layout_marginLeft="3sp"
  42. android:layout_marginRight="8sp"
  43. android:layout_weight="1"
  44. android:background="@drawable/startbutton"
  45. android:text="取消" />
  46. </LinearLayout>
  47. </LinearLayout>
  48. </RelativeLayout>

显然,这个方式比较笨拙,我们可以对此进行一个封装,利用Handler和Eunnable,看下面的代码:

[html] view plaincopy

  1. package com.example.daojishi;
  2. import android.os.Handler;
  3. import android.util.Log;
  4. public class MyCountDownTimer {
  5. private long millisInFuture;
  6. private long countDownInterval;
  7. private boolean status;
  8. public MyCountDownTimer(long pMillisInFuture, long pCountDownInterval) {
  9. this.millisInFuture = pMillisInFuture;
  10. this.countDownInterval = pCountDownInterval;
  11. status = false;
  12. Initialize();
  13. }
  14. public void Stop() {
  15. status = false;
  16. }
  17. public long getCurrentTime() {
  18. return millisInFuture;
  19. }
  20. public void Start() {
  21. status = true;
  22. }
  23. public void Initialize() {
  24. final Handler handler = new Handler();
  25. Log.v("status", "starting");
  26. final Runnable counter = new Runnable() {
  27. public void run() {
  28. long sec = millisInFuture / 1000;
  29. if (status) {
  30. if (millisInFuture <= 0) {
  31. Log.v("status", "done");
  32. } else {
  33. Log.v("status", Long.toString(sec) + " seconds remain");
  34. millisInFuture -= countDownInterval;
  35. handler.postDelayed(this, countDownInterval);
  36. }
  37. } else {
  38. Log.v("status", Long.toString(sec)
  39. + " seconds remain and timer has stopped!");
  40. handler.postDelayed(this, countDownInterval);
  41. }
  42. }
  43. };
  44. handler.postDelayed(counter, countDownInterval);
  45. }
  46. }

这个类就是负责倒计时的类,下面结合Activity,看一下怎么用:

[html] view plaincopy

  1. package com.example.daojishi;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.os.Handler;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.widget.Button;
  8. import android.widget.TextView;
  9. public class CounterActivity extends Activity {
  10. /** Called when the activity is first created. */
  11. TextView timeText;
  12. Button startBut;
  13. Button stopBut;
  14. MyCountDownTimer mycounter;
  15. @Override
  16. public void onCreate(Bundle savedInstanceState) {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.main);
  19. timeText = (TextView) findViewById(R.id.time);
  20. startBut = (Button) findViewById(R.id.start);
  21. stopBut = (Button) findViewById(R.id.stop);
  22. mycounter = new MyCountDownTimer(20000, 1000);
  23. RefreshTimer();
  24. }
  25. public void StartTimer(View v) {
  26. Log.v("startbutton", "开始倒计时");
  27. mycounter.Start();
  28. }
  29. public void StopTimer(View v) {
  30. Log.v("stopbutton", "暂停倒计时");
  31. mycounter.Stop();
  32. }
  33. public void RefreshTimer() {
  34. final Handler handler = new Handler();
  35. final Runnable counter = new Runnable() {
  36. public void run() {
  37. timeText.setText(Long.toString(mycounter.getCurrentTime()));
  38. handler.postDelayed(this, 100);
  39. }
  40. };
  41. handler.postDelayed(counter, 100);
  42. }
  43. }

布局文件:

[html] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical"
  6. android:weightSum="1" >
  7. <TextView
  8. android:id="@+id/time"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:text="TextView"
  12. android:textAppearance="?android:attr/textAppearanceLarge" >
  13. </TextView>
  14. <Button
  15. android:id="@+id/start"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:onClick="StartTimer"
  19. android:text="Start" >
  20. </Button>
  21. <Button
  22. android:id="@+id/stop"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content"
  25. android:onClick="StopTimer"
  26. android:text="Stop" >
  27. </Button>
  28. </LinearLayout>

这样就可以比较方便地使用倒计时功能了。但是还有一个更简单的方法。

在Android中有一个CountDownTimer类,这个类就是用来实现类似倒计时方面的功能。使用的时候,只需要继承自CountDownTimer并实现它的方法。

[html] view plaincopy

  1. import android.app.Activity;
  2. import android.os.Bundle;
  3. import android.content.Intent;
  4. import android.os.CountDownTimer;
  5. import android.widget.TextView;
  6. import android.widget.Toast;
  7. public class NewActivity extends Activity {
  8. private MyCount mc;
  9. private TextView tv;
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.main);
  14. tv = (TextView)findViewById(R.id.show);
  15. mc = new MyCount(30000, 1000);
  16. mc.start();
  17. }
  18. /*定义一个倒计时的内部类*/
  19. class MyCount extends CountDownTimer {
  20. public MyCount(long millisInFuture, long countDownInterval) {
  21. super(millisInFuture, countDownInterval);
  22. }
  23. @Override
  24. public void onFinish() {
  25. tv.setText("done");
  26. }
  27. @Override
  28. public void onTick(long millisUntilFinished) {
  29. tv.setText("seconds remaining: " + millisUntilFinished / 1000);
  30. }
  31. }
  32. }

onFinish()方法是本次倒计时结束的时候调用的,onTick是每隔1秒钟执行的,我们就是在这里执行重复的任务,像本例子的显示时间。执行完后会自动取消,如果在期间停止的话,可以调用cancel()方法。看一下它的源码就会发现,它是使用Handler+SystemClock来实现的。

[html] view plaincopy

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. *      http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.os;
  17. import android.util.Log;
  18. /**
  19. * Schedule a countdown until a time in the future, with
  20. * regular notifications on intervals along the way.
  21. *
  22. * Example of showing a 30 second countdown in a text field:
  23. *
  24. * <pre class="prettyprint">
  25. * new CountDownTimer(30000, 1000) {
  26. *
  27. *     public void onTick(long millisUntilFinished) {
  28. *         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
  29. *     }
  30. *
  31. *     public void onFinish() {
  32. *         mTextField.setText("done!");
  33. *     }
  34. *  }.start();
  35. * </pre>
  36. *
  37. * The calls to {@link #onTick(long)} are synchronized to this object so that
  38. * one call to {@link #onTick(long)} won‘t ever occur before the previous
  39. * callback is complete.  This is only relevant when the implementation of
  40. * {@link #onTick(long)} takes an amount of time to execute that is significant
  41. * compared to the countdown interval.
  42. */
  43. public abstract class CountDownTimer {
  44. /**
  45. * Millis since epoch when alarm should stop.
  46. */
  47. private final long mMillisInFuture;
  48. /**
  49. * The interval in millis that the user receives callbacks
  50. */
  51. private final long mCountdownInterval;
  52. private long mStopTimeInFuture;
  53. /**
  54. * @param millisInFuture The number of millis in the future from the call
  55. *   to {@link #start()} until the countdown is done and {@link #onFinish()}
  56. *   is called.
  57. * @param countDownInterval The interval along the way to receive
  58. *   {@link #onTick(long)} callbacks.
  59. */
  60. public CountDownTimer(long millisInFuture, long countDownInterval) {
  61. mMillisInFuture = millisInFuture;
  62. mCountdownInterval = countDownInterval;
  63. }
  64. /**
  65. * Cancel the countdown.
  66. */
  67. public final void cancel() {
  68. mHandler.removeMessages(MSG);
  69. }
  70. /**
  71. * Start the countdown.
  72. */
  73. public synchronized final CountDownTimer start() {
  74. if (mMillisInFuture <= 0) {
  75. onFinish();
  76. return this;
  77. }
  78. mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
  79. mHandler.sendMessage(mHandler.obtainMessage(MSG));
  80. return this;
  81. }
  82. /**
  83. * Callback fired on regular interval.
  84. * @param millisUntilFinished The amount of time until finished.
  85. */
  86. public abstract void onTick(long millisUntilFinished);
  87. /**
  88. * Callback fired when the time is up.
  89. */
  90. public abstract void onFinish();
  91. private static final int MSG = 1;
  92. // handles counting down
  93. private Handler mHandler = new Handler() {
  94. @Override
  95. public void handleMessage(Message msg) {
  96. synchronized (CountDownTimer.this) {
  97. final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
  98. if (millisLeft <= 0) {
  99. onFinish();
  100. } else if (millisLeft < mCountdownInterval) {
  101. // no tick, just delay until done
  102. sendMessageDelayed(obtainMessage(MSG), millisLeft);
  103. } else {
  104. long lastTickStart = SystemClock.elapsedRealtime();
  105. onTick(millisLeft);
  106. // take into account user‘s onTick taking time to execute
  107. long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
  108. // special case: user‘s onTick took more than interval to
  109. // complete, skip to next interval
  110. while (delay < 0) delay += mCountdownInterval;
  111. sendMessageDelayed(obtainMessage(MSG), delay);
  112. }
  113. }
  114. }
  115. };
  116. }

所以,如果你的程序需要执行一些周期性的任务,就可以考虑使用CountDownTimer这个类了。需要注意的是,在上面的这个例子中,最后显示时间是1,也就是说其实上执行了29次。所以这个地方一定要注意,如果你的任务次数是n,那么设置的时候一定要注意设置成n+1的时间。
    
    最后,欢迎大家评论交流,谢谢。

时间: 2024-10-23 22:07:37

Android 关于倒计时功能的说说的相关文章

Android倒计时功能的实现(CountDownTimer)

以前编程的时候,遇到倒计时的功能时,经常自己去写,但其实Android已经帮封装好了一个倒计时类CountDownTimer,其实是将后台线程的创建和Handler队列封装成为了一个方便的类调用. 说明: CountDownTimer timer = new CountDownTimer(30000, 1000)中,第一个参数表示总时间,第二个参数表示间隔时间. 意思就是每隔一秒会回调一次方法onTick,然后30秒之后会回调onFinish方法. package com.androidcoun

Android基础之——CountDownTimer类,轻松实现倒计时功能

在发现这个类之前,一直是用的handler,子线程发消息,UI线程进行倒计时的显示工作.前几天在做一个倒计时显示的时候发现了这个类,用起来很方便 翻看了下源码,内部已经帮我们实现了handler的子线程操作 CountDownTimer这个类用起来很简单,两个参数,几句代码搞定,如下: CountDownTimer(long millisInFuture, long countDownInterval) 构造函数有两个参数,第一个millisInFuture是指要倒计时的总时间,单位是long

Android开发:验证码倒计时功能实现

前言 现在好多个APP里面都有验证码倒计时按钮,实现方式大概有下面几种: 1.使用线程和Handler的方式,定时刷新倒计时数字,这种方式容易导致内存泄露,所以一般都使用弱引用,控制数字的刷新. 2.自定义倒计时按钮 3.使用Android提供的CountDownTimer结合TextView实现倒计时功能 这篇主要就是说下用第三种方式实现,简单好用 效果图 实现 以下是核心代码: /** * Created by hfs on 2017/5/9. */ public class TimeCou

(六)Android中使用CountDownTimer实现倒计时功能

一.倒计时运行效果图 开发中经常遇到获取短信验证码后需要等待1分钟倒计时,这时需要一个倒计时程序.本文利用CountDownTimer封装了一个比较好用的倒计时工具类,方便以后程序开发.下面是倒计时功能的运行效果图: 二.此工程结构如下所示: 三.此工程中各个重点文件的代码如下所示: 3.1 TimeCount.java是实现倒计时的工具类,此工具类可以在很多倒计时场合使用,此类中的代码如下所示: package com.example.timecountdemo; import android

App启动页倒计时功能

转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6753418.html 示例代码采用 RxJava + RxLifecycle + Data-Binding 模式编写 示例图: 话不多说,实现方式如下: 1.导入依赖库 ① RxJava: Reactive Extensions for the JVM compile 'io.reactivex:rxjava:1.2.9' compile 'io.reactivex:rxandroid:1.2.1' ②

集成Android免费语音合成功能(在线、离线、离在线融合)

集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离线)集成Android免费语音合成功能(在线.离线.离在线融合),有这一篇文章就够了(离在线融合) 转眼间,大半年没写文章了,没什么理由,就是人变懒了.囧~ 看标题,其实大家都被骗了,有这一篇文章还不够,我其实是打算分3篇文章来写的,如果合在一章里面就太长了,不过现在这个标题党横行的网络世界,我也被污染了,哈.那么为什么要分3篇文章来讲呢?看标题也能猜到了,就是在线.离线.离在线融合这3种语音合成方式,我将分别使

自己封装的一个简单的倒计时功能

因为平常工作中很常用到该功能,所以就利用这次国庆假期,重新梳理与对原有代码进行改善,再集成一个常用的功能,最终封装出这个“简单倒计时”功能. 该倒计时方法具有以下该功能: 1. 根据指定日期与当前的电脑时间进行匹配 2. 通过指定一个数组参数,来设置在每一天内不同的时间段进行倒计时. * 该方法还未通过实际工作的检测,稳定性未知(如果实际工作通过,会删除这段话) 1 function countDown(date,target,filter){ 2 3 var setTime = new Dat

Android &#39;记住密码&#39;功能

1.运行后界面图 2.主要代码: 2.1 activity_main.xml(2个TextView 2个EditText 1个CheckBox以及1个Button): 1 <TextView 2 android:id="@+id/tvAccount" 3 android:layout_width="wrap_content" 4 android:layout_height="wrap_content" 5 android:layout_al

android CountDownTimer 倒计时

在倒计时通过自己曾用所有的时间handle延迟发送,实现.但最近Android其中发现,一类,它是Android倒计时提供实现类.使用简单,原则上也通过handle对于倒计时: 一个简单的小李子: private TextView text; private CountDownTimer timer = new CountDownTimer(10000, 1000) { @Override public void onTick(long millisUntilFinished) { text.s