How to Stop Timer in Text View

How to stop timer in Text view?

Here is a demo of possible approach - as .timer run from now for ever (by design), the idea is to replace it with regular text once specified period is over.

Tested with Xcode 12b3 / iOS 14.

demo

struct DemoView: View {
@State private var run = false

var body: some View {
VStack {
if run {
Text(nextRollTime(in: 10), style: .timer)
} else {
Text("0:00")
}
}
.font(Font.system(.title, design: .monospaced))
.onAppear {
self.run = true
}
}

func nextRollTime(in seconds: Int) -> Date {
let date = Calendar.current.date(byAdding: .second, value: seconds, to: Date())
DispatchQueue.main.asyncAfter(deadline: .now() + Double(seconds)) {
self.run = false
}
return date ?? Date()
}
}

countdown timer in text view

Issue: You set 1 in each argument in duration2 variable, so the TextView won't ever be changed, you need to set the actual value that is changed on every timer tick which is the parameter of the onTick() method >> millisUntilFinished

Change your timer to:

new CountDownTimer(duration, 1000) {
@Override
public void onTick(long millisUntilFinished) {
String duration2 = String.format(Locale.ENGLISH, "%02d : %02d"
, TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) //<<<<< change here
, TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - //<<<< change here
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished))); //<<<<< change here

//set converted time to textView
txtTimer.setVisibility(View.VISIBLE);
txtTimer.setText(duration2+"");
btnOk.setText(duration2);
}

@Override
public void onFinish() {
//when timer finished, hide text view
txtTimer.setVisibility(View.INVISIBLE);
btnGetPinCode.setBackgroundResource(R.drawable.button);
btnGetPinCode.setClickable(true);
}
}.start();

How to stop timer in timer task and re-enable a button after timer stops?

First, make your Intent an instance variable like-

private Button btn_start;
private TextView tv_timer;
.
.
private Intent intent_service;

inside init() your code should look like-

intent_service = new Intent(getApplicationContext(), Timer_Service.class);
.
.

if (mpref.getBoolean("finish", false)) {
et_hours.setEnabled(false);
btn_start.setEnabled(true);
tv_timer.setText("");
} else {

et_hours.setEnabled(false);
btn_start.setEnabled(false); // a change is here
tv_timer.setText(str_value);
}

and inside the onClick(View v) add this line of code-

mEditor.putBoolean("finish", false).commit();
.
.
startService(intent_service); // start the service

Now change your BroadcastReceiver-

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String str_time = intent.getStringExtra("time");
tv_timer.setText(str_time);

}
};

To

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String str_time = intent.getStringExtra("time");
tv_timer.setText(str_time);
if (str_time.equals("00:00")) {
stopService(intent_service); // stop service after work done
btn_start.setEnabled(true);
}

}
};

and now make a small change in your Timer_Service class-

if (long_hours == 0){
mEditor.putBoolean("finish", true).commit(); // a change is here
mTimer.cancel();
}

try it and let me know if it works.

Stop Timer() in custom TextView

Override the onDetachedFromWindow() method in your custom TextView, and call stopTimer() in there.

How to display a timer in a TextView in Android?

int time=30;
TextView textTimer = (TextView)findViewById(R.id.timer);

new CountDownTimer(30000, 1000) {

public void onTick(long millisUntilFinished) {
textTimer.setText("0:"+checkDigit(time));
time--;
}

public void onFinish() {
textTimer.setText("try again");
}

}.start();



public String checkDigit(int number) {
return number <= 9 ? "0" + number : String.valueOf(number);
}

CountDownTimer flickers between seconds

Every time onStart fires (e.g. by going to the home screen then back into the app) if the current timer still has time left, you start another one through that startVisibleCountdown() call. You haven't shown you're stopping the old one anywhere - your code isn't even keeping a reference to it, it's just started anonymously, and runs until it completes (or the app is killed)

If you have multiple timers running, they all set timeLeft according to the value passed into their onTick, and then they call the function that displays that. Since their updates are all getting posted to the message queue, it's possible there's a slight timing discrepancy between them (e.g. one has millisUntilFinished = 6000 and one has 5999) and you're getting them out of order.

That would explain why it's changing at all (you have multiple timers setting the text on the TextView when there should only be one) and why it's going backwards (no hard guarantees about which message is at the front of the queue or even when it arrives exactly)

So you need to make sure you're only ever running one instance of your timer - there are a few ways to handle that, this is probably the safest approach (not thread-safe but that's not an issue with what you're doing here):

private var myTimer: CountdownTimer? = null

...

fun startVisibleCountdown() {
// enforce a single current timer instance
if (myTimer != null) return
myTimer = object : CountDownTimer(timeLeftInMillisecondsVisibleCounter, 1000) {
...
override fun onFinish() {
// if a timer finishes (i.e. it isn't cancelled) clear it so another can be started
myTimer = null
}
}
}

...

override fun onStop() {
...
// probably better in a function called stopVisibleCountdown() for symmetry and centralising logic
myTimer?.run { cancel() }
myTimer = null
}

That way, there's only one place you're actually creating and starting a timer, and that code ensures only one instance is running at a time. That instance is only cleared when the timer successfully finishes, or when it's explicitly stopped. By centralising it like this (and putting all your defensive coding in one place) you can call the start function from multiple places (onStart, some button's onClick) and it will all be handled safely

How to stop fading animation of textview?

you can stop your TextView animation after some seconds with this way :

new Handler().postDelayed(new Runnable() {
@Override
public void run() {
fadingTextView.stop();
}
}, Time_TO_STOP);


Related Topics



Leave a reply



Submit