Android Count Down Timer Tutorial
A countdown is a sequence of backward counting to indicate the time remaining before an event is scheduled to occur. To achieve countdown Android comes with a built-in CountDownTimer class for constructing CountDownTimers. Its easy to use, efficient and works.This class is an abstract class whose methods need to be overridden to implement it in our project.
Let’s Get it Working
In this tutorial we are going to learn the basic usage of CountDownTimer. To really understand the usage of count down timer we will create an app. This app show the circular progress bar , time and start/stop image to control the count down timer.
Basic Usage
Implementing a Count Down Timer in your app won’t take more than two steps. First you need to create an object of in-built abstract class named CountDownTimer. This class is used to Schedule a countdown until a time in the future, with regular notifications on intervals along the way.
CountDownTimer countDownTimer = new CountDownTimer(60000, 1000) { public void onTick(long millisUntilFinished) { mTextView.setText("Seconds Remaining: " + millisUntilFinished / 1000); } public void onFinish() { mTextView.setText("Time Up!"); } };
Second you have to start the count down timer via invoking start() method.
countDownTimer.start();
Step 1) Creating New Project
Create a new project in Android Studio from File ⇒ New Project Fill the required information like project name and package name of the project. When it prompts you to select the default activity, select Empty Activity and proceed.
Step 2) Defining strings,colors and styles
2.1 Add the below string values to the strings.xml located in res ⇒ values ⇒ strings.xml.
<resources> <string name="app_name">Count Down Timer</string> <string name="hint_minute">Minute</string> <string name="message_minutes">Please Enter Minutes...</string> </resources>
2.2 Add the below color values to the colors.xml located in res ⇒ values ⇒ colors.xml.
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#1E2538</color> <color name="colorPrimaryDark">#0E121B</color> <color name="colorAccent">#F5FA55</color> <color name="colorBackground">#151B29</color> <color name="colorYellow">#F5FA55</color> </resources>
2.3 Add the below style values to the styles.xml located in res ⇒ values ⇒ styles.xml.
<resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources>
Step 3) Adding drawable
Before creating layout we have to write custom drawable xmls for circular progress bar .And also need some images for start, stop and reset icon.
3.1 Create new drawable resource file by right click on drawable ⇒ New ⇒ Drawable resource file name it drawable_circle_yellow.xml and add the below code to it. This file will create a yellow hollow circle of 10dp of thicknes.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadiusRatio="2.3" android:shape="ring" android:thickness="10dp" android:useLevel="true"> <solid android:color="@color/colorYellow" /> </shape>
3.2 Again Create new drawable resource file by right click on drawable ⇒ New ⇒ Drawable resource file name it drawable_circle_dark_blue.xml and add the below code to it. This file will create a blue hollow circle of 10dp of thicknes.
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadiusRatio="2.3" android:shape="ring" android:thickness="10dp" android:useLevel="false"> <solid android:color="@color/colorPrimaryDark" /> </shape>
3.3 Download the images zip. Unzip it and place all the images in drawable folder.
Step 4) Creating the layout
Now add the below code to activity_main.xml located in res ⇒ layout ⇒ activity_main.xml. This code will create a view show above in the screen shot i.e a circular progress bar to show the time elapsed progress, input field to enter minutes, text field to show the time, start/stop and reset image to control the count down timer.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorBackground"> <ProgressBar android:id="@+id/progressBarCircle" style="?android:attr/progressBarStyleHorizontal" android:layout_width="270dp" android:layout_height="270dp" android:layout_centerInParent="true" android:background="@drawable/drawable_circle_dark_blue" android:indeterminate="false" android:max="100" android:progress="100" android:progressDrawable="@drawable/drawable_circle_yellow" android:rotation="-90" /> <EditText android:id="@+id/editTextMinute" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/textViewTime" android:layout_centerHorizontal="true" android:layout_marginBottom="10dp" android:gravity="center" android:hint="@string/hint_minute" android:inputType="number" android:maxLength="15" android:maxLines="1" android:minEms="5" android:text="1" android:textColor="@color/colorYellow" android:textColorHint="@color/colorYellow" /> <TextView android:id="@+id/textViewTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="00:01:00" android:textColor="@color/colorYellow" android:textSize="40sp" /> <ImageView android:id="@+id/imageViewReset" android:layout_width="30dp" android:layout_height="30dp" android:layout_below="@+id/textViewTime" android:layout_centerInParent="true" android:layout_marginTop="30dp" android:src="@drawable/icon_reset" android:visibility="gone" /> <ImageView android:id="@+id/imageViewStartStop" android:layout_width="50dp" android:layout_height="50dp" android:layout_below="@+id/progressBarCircle" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" android:src="@drawable/icon_start" /> </RelativeLayout>
Step 5) Writing Code in MainActivity class
Now add the below code to MainActivity.java located in java ⇒ project’s package ⇒ MainActivity. Here i have written code to initialize views, added click listeners on it ,methods to control start stop reset functionality.
→ initViews() to intialize views.
→ initListeners() to initialize the click listeners.
→ setTimerValues() fetches the input minute value from the edit text, convert minutes to milliseconds that is required for count down timer.
→ startCountDownTimer() initializes the abstract class count down timer object with two implemented methods onTick(long milliSeconds) and onFinish(). onTick(long milliSeconds) Callback is fired on regular interval and onFinish() Callback is fired when the time is up. With count down timer object i started it by calling countDownTimer.start();
→ stopCountDownTimer() stops the count down timer by calling cancel() method.
→ startStop() contains start/stop functionality for count down timer and also make changes in views.
→ hmsTimeFormatter(long milliSeconds) convert the milliseconds to HH:mm:ss time format.
package com.androidtutorialshub.countdowntimer; import android.os.Bundle; import android.os.CountDownTimer; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.util.concurrent.TimeUnit; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private long timeCountInMilliSeconds = 1 * 60000; private enum TimerStatus { STARTED, STOPPED } private TimerStatus timerStatus = TimerStatus.STOPPED; private ProgressBar progressBarCircle; private EditText editTextMinute; private TextView textViewTime; private ImageView imageViewReset; private ImageView imageViewStartStop; private CountDownTimer countDownTimer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // method call to initialize the views initViews(); // method call to initialize the listeners initListeners(); } /** * method to initialize the views */ private void initViews() { progressBarCircle = (ProgressBar) findViewById(R.id.progressBarCircle); editTextMinute = (EditText) findViewById(R.id.editTextMinute); textViewTime = (TextView) findViewById(R.id.textViewTime); imageViewReset = (ImageView) findViewById(R.id.imageViewReset); imageViewStartStop = (ImageView) findViewById(R.id.imageViewStartStop); } /** * method to initialize the click listeners */ private void initListeners() { imageViewReset.setOnClickListener(this); imageViewStartStop.setOnClickListener(this); } /** * implemented method to listen clicks * * @param view */ @Override public void onClick(View view) { switch (view.getId()) { case R.id.imageViewReset: reset(); break; case R.id.imageViewStartStop: startStop(); break; } } /** * method to reset count down timer */ private void reset() { stopCountDownTimer(); startCountDownTimer(); } /** * method to start and stop count down timer */ private void startStop() { if (timerStatus == TimerStatus.STOPPED) { // call to initialize the timer values setTimerValues(); // call to initialize the progress bar values setProgressBarValues(); // showing the reset icon imageViewReset.setVisibility(View.VISIBLE); // changing play icon to stop icon imageViewStartStop.setImageResource(R.drawable.icon_stop); // making edit text not editable editTextMinute.setEnabled(false); // changing the timer status to started timerStatus = TimerStatus.STARTED; // call to start the count down timer startCountDownTimer(); } else { // hiding the reset icon imageViewReset.setVisibility(View.GONE); // changing stop icon to start icon imageViewStartStop.setImageResource(R.drawable.icon_start); // making edit text editable editTextMinute.setEnabled(true); // changing the timer status to stopped timerStatus = TimerStatus.STOPPED; stopCountDownTimer(); } } /** * method to initialize the values for count down timer */ private void setTimerValues() { int time = 0; if (!editTextMinute.getText().toString().isEmpty()) { // fetching value from edit text and type cast to integer time = Integer.parseInt(editTextMinute.getText().toString().trim()); } else { // toast message to fill edit text Toast.makeText(getApplicationContext(), getString(R.string.message_minutes), Toast.LENGTH_LONG).show(); } // assigning values after converting to milliseconds timeCountInMilliSeconds = time * 60 * 1000; } /** * method to start count down timer */ private void startCountDownTimer() { countDownTimer = new CountDownTimer(timeCountInMilliSeconds, 1000) { @Override public void onTick(long millisUntilFinished) { textViewTime.setText(hmsTimeFormatter(millisUntilFinished)); progressBarCircle.setProgress((int) (millisUntilFinished / 1000)); } @Override public void onFinish() { textViewTime.setText(hmsTimeFormatter(timeCountInMilliSeconds)); // call to initialize the progress bar values setProgressBarValues(); // hiding the reset icon imageViewReset.setVisibility(View.GONE); // changing stop icon to start icon imageViewStartStop.setImageResource(R.drawable.icon_start); // making edit text editable editTextMinute.setEnabled(true); // changing the timer status to stopped timerStatus = TimerStatus.STOPPED; } }.start(); countDownTimer.start(); } /** * method to stop count down timer */ private void stopCountDownTimer() { countDownTimer.cancel(); } /** * method to set circular progress bar values */ private void setProgressBarValues() { progressBarCircle.setMax((int) timeCountInMilliSeconds / 1000); progressBarCircle.setProgress((int) timeCountInMilliSeconds / 1000); } /** * method to convert millisecond to time format * * @param milliSeconds * @return HH:mm:ss time formatted string */ private String hmsTimeFormatter(long milliSeconds) { String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(milliSeconds), TimeUnit.MILLISECONDS.toMinutes(milliSeconds) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliSeconds)), TimeUnit.MILLISECONDS.toSeconds(milliSeconds) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliSeconds))); return hms; } }
Enjoy Coding and Share Knowledge