2

I am in the dawn of my Android programming adventure and have just become able to communicate between on-screen views. So the next step for me is to successfully pull text from a TextView (set by a Dialog) and use a Start Button to run a Timer based on the user selected Dialog (default to the current minute value of the clock).

Here is what you see on screen.

  1. A TextView that displays the selection from the Dialog.
  2. A Selector Button that launches the Dialog TimePicker Dialog and resets the Start Button.
  3. A Start Button that (should) read the TextView, disable itself, and begin a CountDownTimer based on a Long extracted from the TextView string.
  4. A debug TextView that displays to me what is actually seen by the system.

The entire activity consists of a single Java File with two Classes declared and of course an XML. Every time I click my start button, despite the Debug TextView showing that I properly extracted the Long value for the seconds the timer instantly completes. I can see from my debug TextView that when I select say.. 08:26, the pSecondsLeft=26 as it should.. but the timer still doesn't count down from 26. I can't see my mistake.

Here is the XML first.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:orientation="vertical">
    <TextView android:id="@+id/timeDisplay"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center_horizontal"
              android:text="Time will appear here after being selected"
              android:textSize="30sp"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button android:id="@+id/pickTime"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Change the time"/>

        <Button android:id="@+id/startTimer"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Start the time"
                />

    </LinearLayout>

    <TextView android:id="@+id/timeRemaining"
              android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:layout_gravity="center_horizontal"
              android:textSize="30sp"
              android:text="Time Remaining"
              />


</LinearLayout>

And here is my Main Activity.

package com.stembo.android.botskooltimepickertutorial;

import java.util.Calendar;
import java.util.StringTokenizer;

import android.app.Activity;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

public class TimePickerActivity extends Activity {
    /** Private members of the class */
    private TextView displayTime;
    private Button pickTime;
    private Button startTimer;
    private TextView timeRemaining;

    private int pMinutesLeft;
    private int pSecondsLeft;
    /** This integer will uniquely define the
     * dialog to be used for displaying time picker.*/
    static final int TIME_DIALOG_ID = 0;

    /** Callback received when the user "picks" a time in the dialog */
    private TimePickerDialog.OnTimeSetListener mTimeSetListener =
            new TimePickerDialog.OnTimeSetListener() {
                public void onTimeSet(TimePicker view, int minLeft, int secLeft) {
                    pMinutesLeft = minLeft;
                    pSecondsLeft = secLeft;
                    updateDisplay();
                    displayToast();
                }
            };

    /** Updates the time in the TextView */
    private void updateDisplay() {
        displayTime.setText(
                new StringBuilder()
                        .append(pad(pMinutesLeft)).append(":")
                        .append(pad(pSecondsLeft)));
    }

    /** Displays a notification when the time is updated */
    private void displayToast() {
        Toast.makeText(this, new StringBuilder().append("Time choosen is ")
                .append(displayTime.getText()),   Toast.LENGTH_SHORT).show();

    }

    /** Add padding to numbers less than ten */
    private static String pad(int c) {
        if (c >= 10)
            return String.valueOf(c);
        else
            return "0" + String.valueOf(c);
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        /** Capture our View elements */
        displayTime = (TextView) findViewById(R.id.timeDisplay);
        pickTime = (Button) findViewById(R.id.pickTime);
        startTimer = (Button) findViewById(R.id.startTimer);
        timeRemaining = (TextView) findViewById(R.id.timeRemaining);

        /** Listener for click event of the pick button */
        pickTime.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                startTimer.setEnabled(true);
                showDialog(TIME_DIALOG_ID);
            }
        });

        /**Listener for click event of the start button */
        startTimer.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                startTimer.setEnabled(false);
                StringTokenizer st = new StringTokenizer(displayTime.getText().toString(), ":");
                while (st.hasMoreElements()){
                    st.nextElement();
                    long pSecondsTimer = Long.parseLong(st.nextToken());
                }
                timeRemaining.setText(displayTime.getText()+" Token="+ pSecondsLeft);
                long oneSecondInterval = 1000;
                MyCount counter = new MyCount(pSecondsLeft, oneSecondInterval);
                counter.start();
            }
        });

        /** Get the current time */
        final Calendar cal = Calendar.getInstance();
        pMinutesLeft = cal.get(Calendar.HOUR_OF_DAY);
        pSecondsLeft = cal.get(Calendar.MINUTE);

        /** Display the current time in the TextView */
        updateDisplay();
    }

    /** Create a new dialog for time picker */

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case TIME_DIALOG_ID:
                return new TimePickerDialog(this,
                        mTimeSetListener, pMinutesLeft, pSecondsLeft, true);
        }
        return null;
    }

    public class MyCount extends CountDownTimer {
        public MyCount(long pSecondsLeft, long countDownInterval){
            super(pSecondsLeft, countDownInterval);
        }

        @Override
        public void onTick(long pSecondsTimer){
            displayTime.setText("Time remaining: " + pSecondsLeft);
        }

        @Override
        public void onFinish(){
            displayTime.setText("Countdown Complete!");
        }
    }
}

Here is the Start Button code which I am having trouble with, its in the Main Activity but may be easier to see excluded.

/**Listener for click event of the start button */
        startTimer.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                startTimer.setEnabled(false);
                StringTokenizer st = new StringTokenizer(displayTime.getText().toString(), ":");
                while (st.hasMoreElements()){
                    st.nextElement();
                    long pSecondsTimer = Long.parseLong(st.nextToken());
                }
                timeRemaining.setText(displayTime.getText()+" Token="+ pSecondsLeft);
                long oneSecondInterval = 1000;
                MyCount counter = new MyCount(pSecondsLeft, oneSecondInterval);
                counter.start();
            }
        });
Stembolt
  • 37
  • 4
  • You should note that onCreateDialog is deprecated. Instead, you should use the new DialogFragment with FragmentManager. – Dave Feb 18 '16 at 20:47

2 Answers2

3

It appears there is a misunderstanding about the values you get back from TimePickerDialog.OnTimeSetListener. It gives you hours and minutes, but you're expecting minutes and seconds. Same for the values coming out of the Calendar you're using on onCreate.

That said, if you are still trying to use a TimePickerDialog to get minutes and seconds with a full understanding that you're reinterpreting the values, you will need to multiply the number of "seconds" you receive from the picker by 1000 to get a unit in milliseconds that you can feed to the CountDownTimer.

MyCount counter = new MyCount(pSecondsLeft * 1000, oneSecondInterval);
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Yes it does give hours and minutes, so I realize that by re-interpreting them I limit myself to a timer of 24 minutes and 59 seconds based on my implementation, but I was just using it as a small step to communicate between things I understand at the moment. Once I have this down my next step will be to replace the timer with some dialog (or whatever) that can go up to 99, or 999 etc. I guess I left some things out of my translation, I'll go re-evaluate based on your input and report back, thanks! – Stembolt Feb 18 '16 at 20:42
0

I think it's because you're not subtracting from the pSecondsLeft variable on each tick

public class MyCount extends CountDownTimer {
        public MyCount(long pSecondsLeft, long countDownInterval){
            super(pSecondsLeft, countDownInterval);
        }

        @Override
        public void onTick(long pSecondsTimer){
            displayTime.setText("Time remaining: " + pSecondsLeft);
            pSecondsLeft --;           
        }

        @Override
        public void onFinish(){
            displayTime.setText("Countdown Complete!");
        }
    }
Phil
  • 4,029
  • 9
  • 62
  • 107