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.
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
How to Access Program Arguments in Swift
Default Value For Optional Generic Parameter in Swift Function
Reading Data into a Struct in Swift
How to Make the Scroll of a Tableview Inside Scrollview Behave Naturally
How to Add Alamofire Url Parameters
How to Draw Text in PDF Context in Swift
Obervableobject Being Init Multiple Time, and Not Refreshing My View
How to Append a Tuple to an Array Object in Swift Code
Trying to Know When a Window Closes in a MACos Document Based Application
Generic Swift 4 Enum With Void Associated Type
Command Compileswiftsources Failed With a Nonzero Exit Code Xcode 10
Identify Face of a Cube Hit on Touches Began in Swift - Scenekit
Lesser Than or Greater Than in Swift Switch Statement
How to Determine the Type of a Variable in Swift
How to Get Directory Size with Swift on Os X
Simpliest Solution to Check If File Exists on a Webserver. (Swift)