1

I'm new to Android development and currently trying to implement a very simple countdown timer, which shall keep on counting after reaching 00:00, but having the text color in red when below 00:00.

I have two problems: 1) It starts counting from one second less than what I set (in the example it starts at 00:09 instead of at 00:10). 2) After it reaches 00:00, on the next tick it turns the text red but keeps the counter on 00:00 (this latter part is not intended), then continue counting as -00:01, -00:02, etc. So it counts twice on 00:00, once in white, once in red. Any ideas why this occurs? Here's my code:

public class myTimerActivity extends Activity {

    Chronometer mainTimer;
    long mStartValue = 10; // Countdown value

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set the user interface for this Activity
        setContentView(R.layout.activity_mytimer);

        // Initialize Chronometer object
        mainTimer = (Chronometer) findViewById(R.id.chronometer);
        mainTimer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
            @Override
            public void onChronometerTick(Chronometer chronometer) {
                if (SystemClock.elapsedRealtime()>=chronometer.getBase()) {
                chronometer.setTextColor(Color.parseColor("#FF0000"));
                };
            }
        });
        mainTimer.setFormat("%s");
        mainTimer.setBase(SystemClock.elapsedRealtime()+mStartValue*1000);
        mainTimer.start();
    }
    ...
}

UPDATE: Here's another implementation, as suggested by Roger:

public class myTimerActivity extends Activity {

    long mStartValue = 10; // Countdown value
    private TextView txtCounter;
    private static final String FORMAT_COUNTER = "%02d:%02d:%02d";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set the user interface for this Activity
        setContentView(R.layout.activity_mytimer);
        txtCounter = (TextView)findViewById(R.id.mTextField);

        new CountDownTimer(mStartValue*1000, 1000) {

            public void onTick(long millisUntilFinished) {
                txtCounter.setText("" + String.format(FORMAT_COUNTER,
                        TimeUnit.MILLISECONDS.toHours(millisUntilFinished), // HOURS PASSED
                        TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millisUntilFinished)), // MINUTES PASSED (over the hours)
                        TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)) // SECONDS PASSED (over the minutes)
                ));
            }

            public void onFinish() {
                txtCounter.setTextColor(Color.parseColor("#FF0000"));
            }
        }.start();

    }
    ...
}
Gugger
  • 21
  • 4
  • I see what you mean, try this and see if it will work for you. http://stackoverflow.com/a/22881494/1867946 – Roger Belk Mar 04 '17 at 18:48
  • Hi Roger, I've implemented the code you've referred to - it runs, but it has very similar problems as mentioned before: 1) it starts a second earlier than expected 2) counts the second to last step twice (00:00:01), and then turns red on this state. (I'm simply setting the color of the text red in the onFinish method.) So apparently, it never reaches the 00:00:00 state on the first place, and takes an extra "tick" to run the onFinish method. If that's of any help, I'm running my code on an emulator. I've tried both API 23 and API 24. – Gugger Mar 12 '17 at 19:40

1 Answers1

0

The problem happens because the framework's Chronometer class calculates seconds by truncating the division of milliseconds, when it should round the result.

I created a custom class that avoids the problem.

See more details here: https://stackoverflow.com/a/76991683/4195337

jmart
  • 2,769
  • 21
  • 36