I'd like a simple mm:ss
timer to be displayed on my actionbar, be able to pick the number of minutes to start counting down from and then call a method once it's at 0. Is this possible and how?
All action buttons and other items available in the action overflow are defined in an XML menu resource. To add actions to the action bar, create a new XML file in your project's res/menu/ directory. The app:showAsAction attribute specifies whether the action should be shown as a button on the app bar.
Android ActionBar is a menu bar that runs across the top of the activity screen in android. Android ActionBar can contain menu items which become visible when the user clicks the “menu” button. In general an ActionBar consists of the following four components: App Icon: App branding logo or icon will be displayed here.
A facility for threads to schedule tasks for future execution in a background thread. Tasks may be scheduled for one-time execution, or for repeated execution at regular intervals. Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially.
The key differences that distinguish the Toolbar from the ActionBar include: Toolbar is a View included in a layout like any other View. As a regular View , the toolbar is easier to position, animate and control. Multiple distinct Toolbar elements can be defined within a single activity.
I've managed to do that by adding a TextView
to the Action Bar as an Action View in the menu, then updating it at regular intervals using a CountDownTimer
.
(Tested on an Android 3.0 emulator, an Android 4.3 emulator and a real device running Android 4.3).
Here's the XML for the menu item. Note that actionViewClass="android.widget.TextVew"
(showAsAction and actionViewClass don't have the android namespace because I'm using the support action bar).
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:compatibility="http://schemas.android.com/apk/res-auto" >
<item android:id="@+id/break_timer"
android:title="@string/break_timer_title"
compatibility:showAsAction="always"
compatibility:actionViewClass="android.widget.TextView" />
</menu>
In onCreateOptionsMenu
, I find the MenuItem
and call getActionView
to assign it to private TextView
, timerText
. I also apply some padding here, so that it's not right at the edge of the screen.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.break_timer, menu);
MenuItem timerItem = menu.findItem(R.id.break_timer);
timerText = (TextView) MenuItemCompat.getActionView(timerItem);
timerText.setPadding(10, 0, 10, 0); //Or something like that...
startTimer(30000, 1000); //One tick every second for 30 seconds
return true;
}
I have a method called startTimer
to start a CountDownTimer
and update timerText
in its onTick
. I call startTimer
from onCreateOptionsMenu
to ensure that timerText
is not accessed before it has been initialised. (Previously, I called startTimer
from onCreate
, but got a NullPointerException
).
private void startTimer(long duration, long interval) {
CountDownTimer timer = new CountDownTimer(duration, interval) {
@Override
public void onFinish() {
//TODO Whatever's meant to happen when it finishes
}
@Override
public void onTick(long millisecondsLeft) {
int secondsLeft = (int) Math.round((millisecondsLeft / (double) 1000));
timerText.setText(secondsToString(secondsLeft));
}
};
timer.start();
}
I'm sure that anyone reading this will know a better way to convert an integer number of seconds to a timecode such as "00:00:00", but just in case I'll share the secondsToString
method I used in onTick
, above.
private String secondsToString(int improperSeconds) {
//Seconds must be fewer than are in a day
Time secConverter = new Time();
secConverter.hour = 0;
secConverter.minute = 0;
secConverter.second = 0;
secConverter.second = improperSeconds;
secConverter.normalize(true);
String hours = String.valueOf(secConverter.hour);
String minutes = String.valueOf(secConverter.minute);
String seconds = String.valueOf(secConverter.second);
if (seconds.length() < 2) {
seconds = "0" + seconds;
}
if (minutes.length() < 2) {
minutes = "0" + minutes;
}
if (hours.length() < 2) {
hours = "0" + hours;
}
String timeString = hours + ":" + minutes + ":" + seconds;
return timeString;
}
Menu xml
<item
android:id="@+id/counter"
android:title=""
android:showAsAction="always">
</item>
**public boolean onCreateOptionsMenu(Menu menu)"
long timer = 10000;
public Boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
final MenuItem counter = menu.findItem(R.id.counter);
new CountDownTimer(timer, 1000) {
public void onTick(long millisUntilFinished) {
long millis = millisUntilFinished;
String hms = (TimeUnit.MILLISECONDS.toHours(millis))+":"+(TimeUnit.MILLISECONDS.toMinutes(millis) -TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)))+":"+ (TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
counter.setTitle(hms);
timer = millis;
}
public void onFinish() {
counter.setTitle("done!");
}
}.start();
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With