I Shared with group to build a Task Timer App, which start timer (stopWatch) when you click on item and when you click again it will stop timer. I used Android Chronometer for that and put it for each item in recyclerview
I faced problem when user start a first timer then scroll down the first one will stopped even the user does not stop it. So I hope to find someone to help me to solve this issue
Thank you
this is an app https://github.com/hsn-amr/Task-Timer
this is a recyclerview adapter
package com.example.tasktimer
import android.app.Application
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.tasktimer.model.Task
import com.example.tasktimer.viewmodel.TaskViewModel
import kotlinx.android.synthetic.main.item_row.view.*
import android.os.SystemClock
import android.util.Log
import android.widget.Chronometer
import androidx.core.view.doOnDetach
import androidx.core.view.isVisible
import com.example.tasktimer.fragments.ViewFragment
import kotlinx.android.synthetic.main.fragment_view.view.*
import androidx.recyclerview.widget.LinearLayoutManager
class HomeRecyclerView(application: Application, val viewFragment: ViewFragment):
RecyclerView.Adapter<HomeRecyclerView.ItemViewHolder>() {
class ItemViewHolder( itemView: View): RecyclerView.ViewHolder(itemView)
private var tasks = emptyList<Task>()
private val taskViewModel by lazy { TaskViewModel(application) }
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
return ItemViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_row,
parent,
false
)
)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.setIsRecyclable(false)
val task = tasks[position]
holder.itemView.apply {
tvTitleInHome.text = task.task
chronometer.text = task.timer
if(task.active){
chronometer.text = task.timer
viewFragment.mainTitle.text = task.task
chronometer.base = SystemClock.elapsedRealtime() - task.pauseOffset
chronometer.start()
chronometer.onChronometerTickListener = Chronometer.OnChronometerTickListener { chronometer ->
viewFragment.mainTime.text = chronometer.text
}
}
tvTitleInHome.setOnClickListener {
viewFragment.mainTitle.text = task.task
if(!task.active){
viewFragment.stopAllOtherTimers(viewFragment.tasks, task.id)
chronometer.base = SystemClock.elapsedRealtime() - task.pauseOffset
chronometer.start()
task.active = true
taskViewModel.updateTask(task)
viewFragment.showingButtons(false)
}else{
task.timer = chronometer.text.toString()
chronometer.stop()
task.pauseOffset = SystemClock.elapsedRealtime() - chronometer.base
task.active = false
chronometer.text = task.timer
taskViewModel.updateTask(task)
viewFragment.showingButtons(true)
}
chronometer.onChronometerTickListener = Chronometer.OnChronometerTickListener { chronometer ->
viewFragment.mainTime.text = chronometer.text
}
viewFragment.pauseButton.setOnClickListener {
pauseTimer(task, chronometer)
}
viewFragment.restartButton.setOnClickListener {
restartTimer(task, chronometer)
}
}
}
}
fun pauseTimer(task: Task, chronometer: Chronometer){
chronometer.base = SystemClock.elapsedRealtime() - task.pauseOffset
chronometer.start()
task.active = true
taskViewModel.updateTask(task)
viewFragment.showingButtons(false)
}
fun restartTimer(task:Task, chronometer: Chronometer){
task.totalTime = getTotalFromString(task.totalTime, chronometer.text.toString())
chronometer.base = SystemClock.elapsedRealtime()
task.pauseOffset = 0
chronometer.start()
task.active = true
taskViewModel.updateTask(task)
viewFragment.showingButtons(false)
}
override fun getItemCount() = tasks.size
fun update(tasks: List<Task>){
this.tasks = tasks
notifyDataSetChanged()
}
private fun getTotalFromString(oldString:String, newString: String): String {
var oldHours = 0
var oldMinutes = 0
var oldSeconds = 0
val oldStringArray = oldString.split(":")
if(oldStringArray.size == 2){
oldMinutes = oldStringArray[0].toInt()
oldSeconds = oldStringArray[1].toInt()
}else{
oldHours = oldStringArray[0].toInt()
oldMinutes = oldStringArray[1].toInt()
oldSeconds = oldStringArray[2].toInt()
}
var newHours = 0
var newMinutes = 0
var newSeconds = 0
val newStringArray = newString.split(":")
if(newStringArray.size == 2){
newMinutes = newStringArray[0].toInt() + oldMinutes
newSeconds = newStringArray[1].toInt() + oldSeconds
}else{
newHours = newStringArray[0].toInt() + oldHours
newMinutes = newStringArray[1].toInt() + oldMinutes
newSeconds = newStringArray[2].toInt() + oldSeconds
}
if(newSeconds>=60){
newMinutes += newSeconds/60
newSeconds %= 60
}
if(newMinutes>=60){
newHours += newMinutes/60
newMinutes %= 60
}
val result = (if (newHours < 10) "0$newHours" else newHours).toString() +
":" + (if (newMinutes < 10) "0$newMinutes" else newMinutes) +
":" + if (newSeconds < 10) "0$newSeconds" else newSeconds
return result
}
}