I need to add 10 seconds:
private fun countdowntimer() {
object : CountDownTimer((time), 1000) {
override fun onTick(millisUntilFinished: Long) {
if ((correct_answers % 5).equals(0) && correct_answers !=0 ) {
// i want to add 10 seconds to countdown timer object also
mTextField.setText("seconds remaining: " + (millisUntilFinished+10000 )/ 1000)
} else {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000)
}
}
override fun onFinish() {
mTextField.setText("done")
//opengameover()
}
}.start()
}
I am not sure but try to multiply with 10 with your calculation like this
(millisUntilFinished+10000 )*10/ 1000
Related
I am experimenting with CountDownTimer in jetpack compose with the following code
#Composable
fun Timer() {
val millisInFuture: Long = 10 * 1000 // TODO: get actual value
val timeData = remember {
mutableStateOf(millisInFuture)
}
val countDownTimer =
object : CountDownTimer(millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
Log.d("TAG", "onTick: ")
timeData.value = millisInFuture
}
override fun onFinish() {
}
}
DisposableEffect(key1 = "key") {
countDownTimer.start()
onDispose {
countDownTimer.cancel()
}
}
Text(
text = timeData.value.toString()
)
}
In the logcat I am able to see the timer is ticking but the UI is not updating .
Please explain why there is on recomposition on changing the value of state variable.
Well, Within the CountDownTimer, instead of setting millisInFuture, you should set millisUntilFinished. That variable holds the updated value, the millisInFuture never changes
timeData.value = millisUntilFinished
You can try this code to implement a Countdown timer:
val time = (timerDate.time).minus(Calendar.getInstance().timeInMillis)
var timer by remember { mutableStateOf(time) }
LaunchedEffect(key1 = timer) {
if (timer > 0) {
delay(1000L)
timer -= 1000L
}
}
val secMilSec: Long = 1000
val minMilSec = 60 * secMilSec
val hourMilSec = 60 * minMilSec
val dayMilSec = 24 * hourMilSec
val hours = (time % dayMilSec / hourMilSec).toInt()
val minutes = (time % dayMilSec % hourMilSec / minMilSec).toInt()
val seconds = (time % dayMilSec % hourMilSec % minMilSec / secMilSec).toInt()
Text(text = String.format("%02d:%02d:%02d", hours, minutes, seconds))
Composable only recompose when there is state change either from the Composable function param or by the value change of State<T> inside the Composable itself like mutableStateOf() or mutableStateListOf(). In your case, you haven't start the countDownTimer itself. Try to call countDownTimer.start() inside the DisposableEffect. Second you set the timeData with the wrong value, try to set it with millisUntilFinished
Im trying to stop Counter when time is over. But in my situation when time is over, timer restart and counting again. I don't know why my onFinish method doesn't work good. Thanks for all support.
countDownTimer = object : CountDownTimer(timeLeftInMillis, 1000) {
override fun onTick(millisUntilFinished: Long) {
timeLeftInMillis = millisUntilFinished
updateCountDownText()
}
override fun onFinish() {
isRunning = false
isStartingAlarm = true
startPauseButton.text = "Start"
startPauseButton.visibility = View.INVISIBLE
resetButton.visibility = View.VISIBLE
alarmSound.start()
}
}.start()
Using the CountDownTimer, is there a way I can let the user choose how much time the timer will count?
val timer = object : CountDownTimer(time * 1000, 1000) {
override fun onTick(millisUntilFinished: Long) {
bntTimer.text = (millisUntilFinished / 1000).toString()
if (!on)
turnOn()
}
override fun onFinish() {
bntTimer.text = "Timer"
if (on)
turnOff()
}
}
In this code the variable time is initialized with 5, but before starting the timer, the user can change it. However, it always count 5 seconds.
Here is where the variable time got modified
bntTimer.setOnClickListener(){
if(TextUtils.isEmpty(etTime.text)) {
Toast.makeText(this, "Por favor, informe o tempo.", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this#MainActivity, "Timer Contando", Toast.LENGTH_SHORT).show()
time = etTime.text.toString().toLong()
timer.start()
}
}
The problem is you are making the timer object first then changing the time variable which has no longer effect on the existing timer object. So you must make the timer object again after changing the time variable.
You can make a function like below or a function with time as a parameter.
fun starTimer(){
time = etTime.text.toString().toLong()
val timer = object : CountDownTimer(time * 1000, 1000) {
override fun onTick(millisUntilFinished: Long) {
bntTimer.text = (millisUntilFinished / 1000).toString()
if (!on)
turnOn()
}
override fun onFinish() {
bntTimer.text = "Timer"
if (on)
turnOff()
}
}.start()
}
Then call the startTimer() function whenever you need it. Something like in your case
bntTimer.setOnClickListener(){
if(TextUtils.isEmpty(etTime.text)) {
Toast.makeText(this, "Por favor, informe o tempo.", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this#MainActivity, "Timer Contando", Toast.LENGTH_SHORT).show()
startTimer()
}
}
I'm using CountdownTimer in my app to display remaining time until specific Date. But Date is only 2 hours from current time, but if I convert millisUntilFinished to hours, it says 9 hours. Date is in UTC format.
remainingTimer = object : CountDownTimer(dateTime.time, 1000) {
override fun onTick(millisUntilFinished: Long) {
remTime = millisUntilFinished
notifyChanged(PAYLOAD_UPDATE_REM_TIME)
}
override fun onFinish() {
swapTimers()
}
}.start()
val hours = ((remTime / (1000 * 60 * 60)).rem(24))
Here you have to specify timer time for how long (2 hour from now = 2*60*60*1000 millis) you want to run
if you convert date in millis its not gonna work the way you want as it return date in millis,
remainingTimer = object : CountDownTimer(2*60*60*1000, 1000) {
override fun onTick(millisUntilFinished: Long) {
remTime = millisUntilFinished
notifyChanged(PAYLOAD_UPDATE_REM_TIME)
}
override fun onFinish() {
swapTimers()
}
}.start()
val hours = ((remTime / (1000 * 60 * 60)).rem(24))
in the timer I use how to add a time when a button is pressed? for example, I want millisUntilFinished to increase by 5 seconds when I press a button. I tried with the global variable but it didn't.
object :CountDownTimer(10000,1000){
override fun onFinish() {
timeText.text = "Left : 0"
handler.removeCallbacks(runnable)
for (image in imageArray){
image.visibility = View.INVISIBLE
}
for (add in timeAdd){
add.visibility = View.INVISIBLE
}
button.visibility = View.VISIBLE
}
override fun onTick(millisUntilFinished: Long) {
timeText.text = "Left : "+millisUntilFinished/1000
}
}.start()
Here is a count down timer we use
fun message(msg:String){
object : CountDownTimer(4000, 1000) {
override fun onTick(millisUntilFinished: Long) {
tvMsg.visibility = View.VISIBLE
tvMsg.text = msg
}
override fun onFinish() {
tvMsg.visibility = View.INVISIBLE
tvMsg.text = ""
}
}.start()
}
And our use of a plain timer
if (result) {
etItemData.setText("")
message("Record Removed")
Timer().schedule(1000){
thisACTIVITY()
}
Kotlin complains about this not sure why
addition to Vector's answer I made an button that display countdown timer every 1 second. I put Vector's answer into a function then call it when my button is pressed. Hope this help someone. With this example it counts down from 4 seconds.
private fun countdown(){
object : CountDownTimer(4000, 1000) {
override fun onTick(millisUntilFinished: Long) {
otp_resend.text = (millisUntilFinished / 1000).toString()
}
override fun onFinish() {
// do something after countdown is done ie. enable button, change color
etc.
otp_resend.text = "done!"
}
}.start()
}
You can't change the remaining time on an already-created CountDownTimer.
Looking at the source, both millisInFuture and countDownInterval are assigned to final variables; you can't change them.
Now, the mStopTimeInFuture variable, the one the timer actually uses to stop, isn't final, and can be changed. But it's a private variable, meaning you'd need to use reflection, and it might not work properly.
If you want a mutable CountDownTimer, you'll need to roll your own (easiest way would probably be to copy the CountDownTimer source and make the mStopTimeInFuture variable public and add milliseconds to it when needed).
As #TheWanderer answered you can not update the millisUntilFinished as there is no such method available in CountDownTimer class.
To update the Timer you need to stop the current timer and start the new timer with updated millisInFuture value. Here is the sample code which will help you to achieve what you want.
var timer: Timer?=null
//Call this method to start timer on activity start
private fun startTimer(){
timer = Timer(10000);
timer?.start()
}
//Call this method to update the timer
private fun updateTimer(){
if(timer!=null) {
val miliis = timer?.millisUntilFinished + TimeUnit.SECONDS.toMillis(5)
//Here you need to maintain single instance for previous
timer?.cancel()
timer = Timer(miliis);
timer?.start()
}else{
startTimer()
}
}
inner class Timer(miliis:Long) : CountDownTimer(miliis,1000){
var millisUntilFinished:Long = 0
override fun onFinish() {
timeText.text = "Left : 0"
handler.removeCallbacks(runnable)
for (image in imageArray){
image.visibility = View.INVISIBLE
}
for (add in timeAdd){
add.visibility = View.INVISIBLE
}
button.visibility = View.VISIBLE
}
override fun onTick(millisUntilFinished: Long) {
this.millisUntilFinished = millisUntilFinished
timeText.text = "Left : "+millisUntilFinished/1000
}
}