Making repetitive CountDownTimer with Different Times - java

I am trying to learn coding. So I decided to make a little project but i stuck.
I am trying to make a CountDownTimer. I have 3 different times. For example first one is 10 sec, second one 5 sec and the third one is 7 sec. So I wanna make an app that start the count from 10 sec and when it finish it start the count from second timer and then third one.
public class MainActivity extends AppCompatActivity {
private Button mStartButton;
private Button mResetButton;
private Button mStopButton;
private TextView mTextViewCountDown;
private TextView mTextViewCounter;
private CountDownTimer mCountDownTimer;
private int countme = 0 ;
private int [] array = new int[3];
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mStartButton = findViewById(R.id.button_start);
mStopButton = findViewById(R.id.button_stop);
mResetButton = findViewById(R.id.button_reset);
mTextViewCountDown = findViewById(R.id.text_view_countdown);
mTextViewCounter = findViewById(R.id.text_s);
array[0]=10000;
array[1]=5000;
array[2]=70000;
mStartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0; i<3; i++){
mCountDownTimer = new CountDownTimer(array[i], 1000) {
#Override
public void onTick(long millisUntilFinished) {
mTextViewCountDown.setText(""+ millisUntilFinished/1000);
}
#Override
public void onFinish() {
countme++;
if(countme / 3 == 3){
mCountDownTimer.cancel();
}else{
start();
} } }.start();
}
}
}); } }
I don't think for loop is right for my problem. It does not increase variable i once, it increase in every ontick i guess. As a beginner, I couldn't figure out what should I do.

You do not need for loop try something like this:
private void startCountDowntimer(long millis, int count) {
count ++;
int finalCount = count;
new CountDownTimer(millis, 1000) {
#Override
public void onTick(long millisUntilFinished) {
mTextViewCountDown.setText(""+ millisUntilFinished/1000);
}
#Override
public void onFinish() {
if (finalCount == 1) {
startCountDowntimer(5000, 1);
} else if (finalCount == 2) {
startCountDowntimer(7000, 2);
} else {
//all finished
}
}
}.start();
}
and on the button click:
mStartButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startCountDowntimer(10000, 0);
}
});

Related

handler.postDelayed not working correctly

I have a simple stopwatch code piece. Thread is running in custom class, it connects to the main activity via Interface
public class MainActivity extends AppCompatActivity implements MainActivityInteractionInterface{
public static boolean isRunning = false;
Stopwatch stopWatch;
private TextView textViewMilliSeconds;
private TextView textViewSeconds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewMilliSeconds = findViewById(R.id.textViewStopwatchMilliseconds);
textViewSeconds = findViewById(R.id.textViewStopwatchSeconds);
stopWatch = new Stopwatch(this, getApplicationContext());
stopWatch.runThread();
}
#Override
public void updateUI() {
String time = String.format(Locale.getDefault(), "%03d", stopWatch.getMilliseconds());
textViewMilliSeconds.setText(time);
String timeSeconds = String.format(Locale.getDefault(), "%02d", stopWatch.getSeconds());
textViewSeconds.setText(timeSeconds);
}
public void startTimer(View view) {
isRunning = !isRunning;
}
public class Stopwatch {
private int milliseconds = 0;
private int seconds = 0;
public int getMilliseconds() {
return milliseconds;
}
public int getSeconds() {
return seconds;
}
private MainActivityInteractionInterface interactionInterface;
private Context applicationContext;
public Stopwatch(MainActivityInteractionInterface interactionInterface, Context applicationContext){
this.interactionInterface = interactionInterface;
this.applicationContext = applicationContext;
}
public void runThread(){
final Handler handler = new Handler();
handler.post(new Runnable(){
#Override
public void run(){
if(isRunning) {
milliseconds++;
if (milliseconds == 1000) {
milliseconds = 0;
seconds++;
if(seconds == 60){
seconds = 0;
}
}
}
interactionInterface.updateUI();
handler.postDelayed(this, 1);
}
});
}
handler should update every 1 millisec, when there is 1000 milliseconds, 1 second passes by
If I set handler.postDelayed delay anything below 15 reaching 1000 milliseconds would take exactly 18 seconds, why?
I don't know why it would take up to 18seconds, but I can tell you this: Android refresh the UI every 16msec (to have a rate of 60fps), so setting the handler to updateUI in a lesser time would make no sense and maybe also interfier with it.
In my humble opinion, make it to update in 20msec and change the counter values according, like this:
handler.post(new Runnable(){
#Override
public void run(){
if(isRunning) {
milliseconds++;
if (milliseconds == 50) {
milliseconds = 0;
seconds++;
if(seconds == 60){
seconds = 0;
}
}
}
interactionInterface.updateUI();
handler.postDelayed(this, 20);
}
});
Look at the second argument of handler.postDelayed(this, 1);
Change it according to the way you increment your milliseconds.

pause program between adding and removing a TextView

I'm working on a tank-game and I have a TextView which represents the shot. Now I want to display the TextView at the specific point and remove it after a second that it looks like the shot goes further step by step. But when I add a countdown or a Thread.sleep the program stops for a second but the TextView doesn't disappear. i want to move the TextView over the screen and after every iteration of my for loop i want to wait a second and then rearrange it again?
Here is the code :
public void shot(float power, float winkel, Button button) {
if(winkel>90) {
winkel = winkel - 10;
}else if(winkel<90){
winkel = winkel +10;
}
for (double i = 0; i<100;i = i+ 1) {
final TextView textView = new TextView(context);
textView.setText(".");
double x = tanks.get(currentTank).getxPos()+(i*power*Math.cos(winkel *(Math.PI/180)));
double y = tanks.get(currentTank).getyPos()+(-1*(i*power*Math.sin(winkel *(Math.PI/180))));
double gravity = (-1*((9.81/2)*Math.pow(i,2)));
y = (y-gravity);
textView.setX((float) x);
textView.setY((float) y);
layout.addView(textView);
for (int j = 0;j<tanks.size();j++){
if(textView.getX()>tanks.get(j).getxPos()&&textView.getX()<tanks.get(j).getxPos()+100){
if(textView.getY()>tanks.get(j).getyPos()&&textView.getY()<tanks.get(j).getyPos()+100){
float k = tanks.get(j).getxPos()-textView.getX();
if(k<0){
k = k*-1;
}
makeDamage(k,tanks.get(j));
}
}
}
new CountDownTimer(2000,1000){
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
layout.removeView(textView);
}
}.start();
}
newTurn();
}
I want to pause the program after adding the TextView for one second and the remove it. The program stops but the TextView doesn't disappear till the for-loop finished. Then all TextViews disappear.
Problem solved:
i've added all positions in a array and then this
public void drawShot(final Button firework, final ArrayList<TextView> toDraw){
final int[] i = {0};
final Handler mHandler = new Handler();
firework.setOnClickListener(new View.OnClickListener() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onClick(View v) {
firework(firework,toDraw.get(i[0]).getX(),toDraw.get(i[0]).getY());
}
});
Runnable runnable = new Runnable() {
#Override
public void run() {
layout.addView(toDraw.get(i[0]));
if(!check(toDraw.get(i[0]))) {
mHandler.postDelayed(this, (long) 1);
}
i[0]++;
}
};
// start it with:
mHandler.post(runnable);
}
probably need to run the remove command on main thread
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
#Override
public void run() {
layout.removeView(textView);
}
};
mainHandler.post(myRunnable);

Count down timer how to implement onfinish method

I have a countdown timer that i want to implement on finish method or some kind of code so that when the timer stops, the text views change to Time's up and another method is initiated (in the activity).
To clarify, the timer is given a starting number that counts down from, to zero in format of xx:xx.
The class of the timer :
public class countdown_timer {
private long pls;
private long millisInFuture;
private long countDownInterval;
private boolean status;
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
this.millisInFuture = pMillisInFuture;
this.countDownInterval = pCountDownInterval;
this.pls = pMillisInFuture;
status = false;
Initialize();
}
public void Stop() {
status = false;
}
public void Reset() {
millisInFuture = pls;
}
public long getCurrentTime() {
return millisInFuture;
}
public void Start() {
status = true;
}
public void Initialize()
{
final Handler handler = new Handler();
Log.v("status", "starting");
final Runnable counter = new Runnable(){
public void run(){
long sec = millisInFuture/1000;
if(status) {
if(millisInFuture <= 0) {
Log.v("status", "done");
} else {
Log.v("status", Long.toString(sec) + " seconds remain");
millisInFuture -= countDownInterval;
handler.postDelayed(this, countDownInterval);
}
} else {
Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
handler.postDelayed(this, countDownInterval);
}
}
};
handler.postDelayed(counter, countDownInterval);
}
The activty that the timer is used:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_card_game_2);
//...find views
mycounterup = new countdown_timer(startcard, 1000);
mycounterdown = new countdown_timer(startcard, 1000);
RefreshTimer();
mycounterdown.Start();
public void RefreshTimer()
{
final Handler handler = new Handler();
final Runnable counter = new Runnable(){
public void run(){
int minutes_up_start = (int) (mycounterup.getCurrentTime() / 1000) / 60;
int seconds_up_start = (int) (mycounterup.getCurrentTime() / 1000) % 60;
String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
card_2_up.setText(time_2_up_start_formatted);
int minutes_down_start = (int) (mycounterdown.getCurrentTime() / 1000) / 60;
int seconds_down_start = (int) (mycounterdown.getCurrentTime() / 1000) % 60;
String card_2_down_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_down_start, seconds_down_start);
card_2_down.setText(card_2_down_start_formatted);
handler.postDelayed(this, 100);
}
};
handler.postDelayed(counter, 100);
}
You can use CountDownTimer:
new CountDownTimer(endsIn * 1000, 1000) {
public void onTick(long millisUntilFinished) {
timerTextView.setText(String.valueOf(millisUntilFinished/1000);
}
public void onFinish() {
}
}.start();
OR:
extend CountDownTimer class:
public class countdown_timer extends CountDownTimer {
TextView textView;
#Override
public void onTick(long millisInFuture) {
long sec = millisInFuture/1000;
if(millisInFuture <= 0) {
Log.v("status", "done");
} else {
Log.v("status", Long.toString(sec) + " seconds remain and timer has stopped!");
}
}
#Override
public void onFinish() {
if(textView != null){
// change text in your textview
}
}
public countdown_timer(long pMillisInFuture, long pCountDownInterval) {
super(pMillisInFuture, pCountDownInterval);
}
public countdown_timer(TextView textView, long pMillisInFuture, long pCountDownInterval) {
super(pMillisInFuture, pCountDownInterval);
this.textView = textView;
}
}
here is a two constructors, one of them is the same as is in your example and in second one you can pass also TextView object and use it in onFinish() method.
UPDATE 2:
Here is CountDownTimer in the Activity:
public class MainActivity extends AppCompatActivity {
TextView textView;
CountDownTimer mycounterdown;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
long startcard = 10000;
textView = (TextView) findViewById(R.id.test);
mycounterdown = new CountDownTimer(startcard, 1000) {
#Override
public void onTick(long mycounterup) {
int minutes_up_start = (int) (mycounterup / 1000) / 60;
int seconds_up_start = (int) (mycounterup / 1000) % 60;
String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
textView.setText(time_2_up_start_formatted);
}
#Override
public void onFinish() {
// call here other methods from activity
testMethod();
}
};
mycounterdown.start();
}
public void testMethod(){
Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
}
}
UPDATE 3: if last tick is one, not zero change count down interval to 500 instead of 1000:
public class MainActivity extends AppCompatActivity {
TextView textView;
CountDownTimer mycounterdown;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
long startcard = 10000;
textView = (TextView) findViewById(R.id.test);
mycounterdown = new CountDownTimer(startcard, 500) {
#Override
public void onTick(long mycounterup) {
int minutes_up_start = (int) (mycounterup / 1000) / 60;
int seconds_up_start = (int) (mycounterup / 1000) % 60;
String time_2_up_start_formatted = String.format(Locale.getDefault(), "%02d:%02d", minutes_up_start, seconds_up_start);
textView.setText(time_2_up_start_formatted);
}
#Override
public void onFinish() {
// call here other methods from activity
testMethod();
}
};
mycounterdown.start();
}
public void testMethod(){
Toast.makeText(MainActivity.this, "Test Method called", Toast.LENGTH_SHORT).show();
}
}
NOTE: take a look at this answer
First, extend CountDownTimer in your timer class.
public class countdown_timer extends CountDownTimer {
}
This allows you to implement some methods.
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
}
Also you must implement constructor that matches super class. You can also add some additional parameters. For example TextView
TextView textView;
public countdown_timer(long millisInFuture, long countDownInterval, TextView txt) {
super(millisInFuture, countDownInterval);
textView = txt;
}
The onFinish() is what you want. Also make sure you are using this class as a CountDownTimer. Then you will be able to start your timer.
Hope it helps.

Pausing a CountDownTimer whilst another one runs - Android

I have two countdown timers in my program, a longer one (120 sec) and a shorter one (3.5 sec). I want the 120 second timer to be paused whilst the 3.5 second timer is running, and for the longer timer to continue running whenever the 3.5 second timer isn't running. So the program starts with the 120 sec remaining whilst the 3.5 sec one runs, then when the 3.5 sec one runs the 120 sec one will start and only pause when the 3.5 sec one runs again (once users presses enter.) How would I do this?
final CountDownTimer loop = new CountDownTimer(3500, 1000) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
number.setVisibility(View.GONE);
final TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setVisibility(View.VISIBLE);
prompt.setText(" Enter the number");
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.VISIBLE);
input.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_ENTER:
Editable answer = input.getText();
int finalAnswer = Integer.parseInt(String.valueOf(answer));
int finalLoadG1 = Integer.parseInt(String.valueOf(number.getText()));
input.setVisibility(View.GONE);
prompt.setVisibility(View.GONE);
if (finalAnswer == finalLoadG1) {
score++;
}
number.setVisibility(View.VISIBLE);
if (score>=0 && score<=2){
int loadG1 = generateG1.nextInt(89999)+10000;
number.setText(""+loadG1);
}
else if (score>=3 && score<=5){
int loadG1 = generateG1.nextInt(899999)+100000;
number.setText(""+loadG1);
}
else if (score>=6 && score<=9){
int loadG1 = generateG1.nextInt(8999999)+1000000;
number.setText(""+loadG1);
}
else if (score>=10 && score<=14){
int loadG1 = generateG1.nextInt(89999999)+10000000;
number.setText(""+loadG1);
}
else if (score>=15 && score<=20){
int loadG1 = generateG1.nextInt(899999999)+100000000;
number.setText(""+loadG1);
}
else if (score>=21) {
int loadG1 = generateG1.nextInt((int) 8999999999L)+1000000000;
number.setText(""+loadG1);
}
input.getText().clear();
start();
return true;
default:
}
}
return false;
}
});
}
}.start();
new CountDownTimer(120000, 1000) {
#Override
public void onTick (long millisUntilFinished) {
}
#Override
public void onFinish() {
TextView result = (TextView) findViewById(R.id.outcome);
result.setText("Score: "+ score);
TextView prompt = (TextView) findViewById(R.id.prompt);
prompt.setVisibility(View.GONE);
final EditText input = (EditText) findViewById(R.id.enterAnswer);
input.setVisibility(View.GONE);
loop.cancel();
number.setVisibility(View.GONE);
}
}.start();
I have asked this before, but was not given a valid answer unfortunately. Would be grateful if anyone is capable of answering this question. Please feel free to insert any code that'll help explain your answer. Many thanks in advance.
Ok, I will try to give an example, but no guarantee that this is exactly what you need:
create a global variable and the CountDownTimer objects:
Long remainingTime = 120000L;
ThreePointFiveSecondsTimer mThreePointFiveSecondsTimer;
HundredTwentySecondsTimer mHundredTwentySecondsTimer;
create the 120 seconds timer:
public class HundredTwentySecondsTimer extends CountDownTimer {
public HundredTwentySecondsTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
}
}
create the 3.5 seconds timer:
public class ThreePointFiveSecondsTimer extends CountDownTimer {
public ThreePointFiveSecondsTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onTick(long millisUntilFinished) {
remainingTime = millisUntilFinished;//set the remaining time
}
#Override
public void onFinish() {
//start the 120 second countdowntimer again
mHundredTwentySecondsTimer = new MyCountDownTimer(remainingTime, 1000);
mHundredTwentySecondsTimer.start();
}
}
start the 120 second timer:
mHundredTwentySecondsTimer = new MyCountDownTimer(remainingTime, 1000);
mHundredTwentySecondsTimer.start();
Then, at any time, you decide to start the 3.5 timer:
mThreePointFiveSecondsTimer = new ThreePointFiveSecondsTimer (3500, 1000);
mThreePointFiveSecondsTimer.start();
mHundredTwentySecondsTimer.cancel();
mHundredTwentySecondsTimer = null;
That´s just the idea behind, but you have to adjust this to your needs. Sorry, but can´t give you all the stuff you need, that will be beyond the frame.
You can try like this (I have not tested but hope it will work)
public class MainActivity extends BaseActivity {
private long remainingTimeForTimer = 0;
private CountDownTimer mCountDownTimer
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Start first timer
test1(120 * 1000);
// now on the basis of remaining timer you can cancel current timer and after that second timer you can start that timer with remaining time
if(remainingTimeForTimer > 0)
{
test1(remainingTimeForTimer);
}
}
private void test1(long totalTimerTime)
{
mCountDownTimer = new CountDownTimer(totalTimerTime, 1000) {
#Override
public void onTick(long millisUntilFinished) {
remainingTimeForTimer = millisUntilFinished;
}
#Override
public void onFinish() {
//trialCount = 0;
}
};
mCountDownTimer.start();
}
#Override
protected void onDestroy() {
if (mCountDownTimer != null) {
mCountDownTimer.cancel();
}
super.onDestroy();
}
}
Resolved
I have resolved this issue after trying multiple times. I ended up putting the larger timer in the onFinish of the shorter one and setting the initial time of that longer timer equal to millisUntilFinished. Then I cancel the long timer when the user presses enter and it automatically starts with the updated time whenever the EditText box is displayed.

How to frequently update number in EditText from loop?

My Code should frequently update a number (not only show the result, delay of 100) from a loop in an EditText after you click on a button.
Old Code:
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
while (repeat > 0) {
num1 = new Random().nextInt(6)+1;
edit1.setText(String.valueOf(num1));
repeat = repeat - 1;
rep.setText(String.valueOf(repeat));
}
}
});
Now I have this:
final Handler randomHandler = new Handler();
final Runnable randomUpdate = new Runnable() {
#Override
public void run() {
num1 = new Random().nextInt(6) + 1;
edit1.setText(String.valueOf(num1));
repeat--;
rep.setText(String.valueOf(repeat));
randomHandler.postDelayed(this, 1000);
}
};
btnpl5.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
repeat = repeat + 5;
rep.setText(String.valueOf(repeat));
button2.setClickable(true);
button2.setEnabled(true);
}
});
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
randomUpdate.run();
button2.setClickable(false);
button2.setEnabled(false);
}
Problem: it won't stop after repeat is 0 (it goes on -1 -2 -3 -4 ..)?
You must always be on the UI thread when calling any method on any
view. If you are doing work on other threads and want to update the
state of a view from that thread, you should use a Handler.
Try this,
handler.postDelayed(new Runnable(){
#Override
public void run() {
num1 = new Random().nextInt(6)+1;
// get previous value and append new generated
edit1.setText(edit1.getText().toString()+String.valueOf(num1));
}
}, (1000)); // run this method in every 1000 milliseconds
This may help you.
You can use an AsyncTask to delay in the background, and publishProgress() to update the UI.
class TextDisplayTask extends AsyncTask<Integer, Integer, Void> {
private int DELAY_MILLIS = 100; // ... set your delay here
#Override
protected Void doInBackground(Integer... params) {
for (int i = 0; i < params[0]; i++) {
int num = new Random().nextInt(6) + 1;
publishProgress(num);
Thread.sleep(DELAY_MILLIS);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
edit1.setText(String.valueOf(values[0]));
}
}
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new TextDisplayTask().execute(20); // show a number 20 times
}
});

Categories