In my app, i'm using two different CountDownTimers that have same values. I have two buttons to control them but when i press the button twice, it starting from the beginning. I want to keep its last value.
Here is my code:
t1 = new CountDownTimer(white, 1000) {
#Override
public void onTick(long l) {
btnWhite.setText("seconds remaining: " + l / 1000);
white = l;
}
#Override
public void onFinish() {
}
};
t2 = new CountDownTimer(black, 1000) {
#Override
public void onTick(long l) {
btnBlack.setText("seconds remaining: " + l / 1000);
black = l;
}
#Override
public void onFinish() {
}
};
btnBlack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
t1.start();
t2.cancel();
}
});
btnWhite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
t2.start();
t1.cancel();
}
});
I have tested this and it works!
I have two TextViews and two Buttons. The black button is next to the black text view and the white button is next to the white text view.
First I declare the important constants.
//contains the elapsed time for each of the timers
long blackElapsed=0,whiteElapsed=0;
//contains the total time with which we start new timers
long totalWhite = 30000;
long totalBlack = 30000;
Next I initialise the CountDownTimers. Whatever you put in here doesn't matter. I only have this so that the timers will be initialised with some value.
The reason is that they have to be initialised in order to be able to .cancel() them later in the OnClickListeners.
black = new CountDownTimer(totalWhite, 1000){
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
}
};
white = new CountDownTimer(totalBlack, 1000){
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
}
};
Finally the OnClickListeners for the buttons. (W is white textView and B is black textView and b is black button and w is white button)
w.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
black.cancel();
//using the elapsed time to start a new timer
totalBlack = totalBlack - blackElapsed;
//this preserves milliseconds by ticking every millisecond
white = new CountDownTimer(totalBlack, 1){
#Override
public void onTick(long l) {
B.setText(l+"");
blackElapsed=totalBlack-l; //updating the elapsed time
}
#Override
public void onFinish() {
}
}.start();
}
});
//we do a similar thing with the other player's button
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
white.cancel();
totalWhite = totalWhite - whiteElapsed;
black = new CountDownTimer(totalWhite, 1){
#Override
public void onTick(long l) {
W.setText(l+"");
whiteElapsed=totalWhite-l;
}
#Override
public void onFinish() {
}
}.start();
}
});
I have checked your code.
It is obvious because your timers initialised with default values. when you start again it won't take new values of white/black.
To achieve what you want you have to initialise timer with new values before starting it.
I have done some correction in your code. you can check that out.
Make Two methods
public void timerStart1(long timeLengthMilli) {
t1 = new CountDownTimer(timeLengthMilli, 1000) {
#Override
public void onTick(long l) {
isRunning1 = true;
tv1.setText("seconds remaining: " + l / 1000);
white = l;
}
#Override
public void onFinish() {
isRunning1 = false;
}
}.start();
}
public void timerStart2(long timeLengthMilli) {
t2 = new CountDownTimer(timeLengthMilli, 1000) {
#Override
public void onTick(long l) {
isRunning2 = true;
tv2.setText("seconds remaining: " + l / 1000);
black = l;
}
#Override
public void onFinish() {
isRunning2 = false;
}
}.start();
}
and set setOnClickListener like this
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!isRunning1) {
isRunning2 = false;
timerStart1(white);
if (t2 != null)
t2.cancel();
}
}
});
button2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!isRunning2) {
isRunning1 = false;
timerStart2(black);
if (t1 != null)
t1.cancel();
}
}
});
UPDATE :
Please check updated code and take these extra variables
boolean isRunning1 = false, isRunning2 = false;
Hope this will help you.
Happy Coding.
Related
In my game the user gets a point when he clicks a button within five seconds. Now I want the timer to decrease the time with every point the user gets - so e.g. with zero points the user has five seconds, and when he has one point he gets only 4.5 seconds to click it again and get the second point. Do I solve it with a for loop?
public class GameScreen extends Activity {
public int score = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
Button count = (Button) findViewById(R.id.button1);
text = (TextView) this.findViewById(R.id.textView3);
tvscore = (TextView) findViewById(R.id.score);
timer();
}
public void gameover() {
Intent intent = new Intent(this, GameOverScreen.class);
startActivity(intent);
}
public void onClick (View view) {
score++;
tvscore.setText(String.valueOf(score));
timer();
}
public void timer(){
new CountDownTimer(5000, 10) {
public void onTick(long millisUntilFinished) {
text.setText(""+String.format("%02d:%03d",
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished)),
TimeUnit.MILLISECONDS.toMillis(millisUntilFinished) - TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished))
));
if(animationRunning) {
cancel();
}
}
public void onFinish() {
text.setText("Too slow.");
gameover();
}
}.start();
}
}
What about doing this:
public void timer(float time) {
new CountDownTimer(time, 10) {
// YOUR CODE
}
}
public void onClick (View view) {
score++;
tvscore.setText(String.valueOf(score));
timer(Math.max(5000-score*500, 2000));
}
I suppose each click (score) will decrease the time with 500 millis...
Limit - Math.max(a, b) will choose the biggest value. Means when 5000-score*500 will be lower than 2000, it will choose 2000 millis instead
Only timer method:
public void timer() {
float time = Math.max(5000-score*500, 2000)
new CountDownTimer(time, 10) {
// YOUR CODE
}
}
So I have 3 timers. For the first one I want only to appear once, because it's something like get ready timer.
For the second and third I want to appear as many times as user wants. Before timers start user must select number of times by pressing on + or - buttons which then set value of a TextView.
That's done with this code:
int counter = 0;
homeScreenPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dodajInterval();
homeScreenMinus.setEnabled(counter > 0);
}
});
homeScreenMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
oduzmiInterval();
homeScreenMinus.setEnabled(counter > 0);
}
});
}
private void oduzmiInterval() {
counter--;
brojIntervala.setText(Integer.toString(counter));
}
private void dodajInterval() {
counter++;
brojIntervala.setText(Integer.toString(counter));
}
And here's the code for timers:
public void homeScreenStart(View view) {
linearniLayoutSetup.setVisibility(View.GONE);
CountDownTimer firstCountDown = new CountDownTimer(seekBarTimerDelay.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
countDownTimerTrci();
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_trci));
}
}.start();
}
public void countDownTimerTrci() {
for (int i = 0; i < counter; i++) {
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
CountDownTimer secondCountDown = new CountDownTimer(seekBarIntervaliVisokogIntenziteta.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
imageViewTimerSlika.setImageResource(R.drawable.ic_timer_niski_intenzitet);
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_hodaj));
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
CountDownTimer thirdCountDown = new CountDownTimer(seekBarIntervaliNiskogIntenziteta.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
countDownTimerTrci();
}
}.start();
}
}.start();
}
}
As you can see, it's a method which is called when button is pressed and I wan't first timer to appear only once and that's why I didn't include it in foor loop.
First timer shows only once and that works, but other two timers keep repeating until I close the app.
Can someone tell me where the problem is?
Try this ,replace your countDownTimerTrci method with mine
public void countDownTimerTrci() {
if(counter>0) {
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_trci));
CountDownTimer secondCountDown = new CountDownTimer(seekBarIntervaliVisokogIntenziteta.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
textViewTimerVrijeme.setText("00:00");
karticaTimera.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
imageViewTimerSlika.setImageResource(R.drawable.ic_timer_niski_intenzitet);
textViewTimerTrciHodajBlaBla.setText(getResources().getString(R.string.timer_hodaj));
toolbar.setBackgroundColor(getResources().getColor(R.color.kartica_hodaj));
CountDownTimer thirdCountDown = new CountDownTimer(seekBarIntervaliNiskogIntenziteta.getProgress() * 1000 + 100, 1000) {
#Override
public void onTick(long millisUntilFinished) {
updateTimer((int) millisUntilFinished / 1000);
}
#Override
public void onFinish() {
counter--;
textViewTimerVrijeme.setText("00:00");
countDownTimerTrci();
}
}.start();
}
}.start();
}
}
When I'm trying to add Start and Cancel in the button I get this error.
I looked into the Timer files but I didn't see anything
"error: non-static method start() cannot be referenced from a static context"
public int number;
public TextView textfield;
Button buton;
int x = 1;
Boolean y = false;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reading);
new CountDownTimer(100000, 1000) {
public void onTick(long millisUntilFinished) {
textfield.setText("Time: " + millisUntilFinished / 1000);
}
public void onFinish() {
textfield.setText("Time is up");
}
}.start();
textfield=(TextView)findViewById(R.id.Zamanlayici);
buton=(Button)findViewById(R.id.Click);
buton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//My Error is in there :(
if (y) {
CountDownTimer.start();
y= true;
}
else {
y = false;
CountDownTimer.cancel();
}
}
});
}
}
You are trying to use not static method like a static. Try to create a variable to store instance of CountDownTimer and call methods on it. Also doc: http://developer.android.com/reference/android/os/CountDownTimer.html
You need to create an instance of CountDownTimer, like so:
CountDownTimer timer = new CountDownTimer(100000, 1000){...}
Then, in the onClick method:
if (y) {
timer.start();
y= true;
}
else {
y = false;
timer.cancel();
}
You need to create an instance of CountDownTimer to call non-static methods from it.
CountDownTimer timer = new CountDownTimer();
timer.start();
Change your code to this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reading);
CountDownTimer timer = new CountDownTimer(100000, 1000) {
public void onTick(long millisUntilFinished) {
textfield.setText("Time: " + millisUntilFinished / 1000);
}
public void onFinish() {
textfield.setText("Time is up");
}
}
timer.start();
textfield=(TextView)findViewById(R.id.Zamanlayici);
buton=(Button)findViewById(R.id.Click);
buton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (y) {
timer.start();
y= true;
}
else {
y = false;
timer.cancel();
}
}
});
}
I'm making an android app where you tap a button to stop a looping counter when it is showing a particular number. I have an array (aNums) holding some int values and want the counter to stop when it is clicked when showing the first number in the array (in this case "2"). For some reason however it decides to stop on "1" when clicked. I'm not sure if my code is just wrong or if there's a timing issue and it's stopping right when it's about to change to the number "2". Here is my code so far:
public class MainActivity extends Activity {
public int a = 0;
private Handler handler = new Handler();
TextView textView2;
Button Stop;
public Runnable myRunnable = new Runnable() {
#Override
public void run() {
updateText();
a = ++a % 10;
if (a < 10) {
handler.postDelayed(this, 1000);
}
}
};
public int aNums[] = { 2, 4, 6, 8, 10, 12 };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView2 = (TextView) findViewById(R.id.textView2);
loop();
Stop = (Button)findViewById(R.id.Stop);
Stop.setOnClickListener(handler2);
}
View.OnClickListener handler2 = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (a == aNums[0]) {
Stop();
}
}
}
public void loop() {
handler.post(myRunnable);
}
public void updateText() {
textView2.setText("" + a);
}
public void Stop() {
super.onStop();
handler.removeCallbacks(myRunnable);
}
}
Does anyone know what the problem is?
Thanks
You forgot two closing brackets here:
View.OnClickListener handler2 = new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i <= aNums.length; i++) {
if (a == aNums[0]) {
Stop();
} //I added this
}
}
}//and this
but I think there is no need for a for loop here: you want to stop the thread when you click at the moment a equals the number in your array at index 0, right?
View.OnClickListener handler2 = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (a == aNums[0]) {
Stop();
}
}
}
Also, this check is not necessary because a will never be 10 or more:
if (a < 10) {
handler.postDelayed(this, 1000);
}
The last thing: when you quit the thread, the text is not updated. Try adding the updateText() after the click:
View.OnClickListener handler2 = new View.OnClickListener() {
#Override
public void onClick(View v) {
if (a == aNums[0]) {
Stop();
updateText();
}
}
}
I'm trying to create a set of buttons that will change a value up or down by 1 with a single tap, and change the value quickly by holding the button. I can't figure out how to get the value to change quickly. Here's what I have:
btPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mTempo=mTempo+1;
setTempo(mTempo + 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btPlus.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public void onLongClick(View view) {
mTempo = mTempo + 1;
setTempo(mTempo + 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mTempo=mTempo-1;
setTempo(mTempo - 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
btMinus.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public void onLongClick(View view) {
mTempo = mTempo - 1;
setTempo(mTempo - 1);
tvTempo.setText(Integer.toString(mTempo));
}
});
return rootView;
}
Thanks for your help.
Holding the button is something else than long clicking it. You need an onTouchListener
In the onPressed method check if the MotionEvent is UP or DOWN and then start/stop counting.
EDIT: Try Counting up in a Thread, something like that:
Final Thread t = new Thread(new Runnable(){
#Override public void run(){
while(!t.isInterrupted(){
setTempo(mTempo++);
}
}
switch (event){
case ACTION_DOWN:
t.start();
break;
case ACTION_UP:
t.interrupt();
break
}