So I,m creating a todo app where user can set priority and priority stars are added programmatically through binding adapter but when scrolling the tasks recycler view Tasks with zero no of stars are also showing stars wheres checking Log it shows zero stars. Also this bug occurs only when i scroll to item with stars and then start scrolling rigorously
I have tried Creating New ArrayList everyTime item is updated
Fragment Code :
viewModel.taskCategory.observe(viewLifecycleOwner, Observer { taskCategoryPair ->
taskCategoryPair?.let {
Log.i("HomeFragment","Submitting New List")
viewModel.filterDataFinish()
adaptor.submitList(it)
}
})
RecyclerView bind code :
RecyclerView.ViewHolder(binding.root) {
fun bind(
task: ToDo,
category: Category,
clickListener: MiscellaneousUtils.GetIdFromClick
) {
binding.task = task
binding.category = category
binding.clickListener = clickListener
binding.onCheckChangeListener = categorizedTasksClickListeners
binding.root.setOnLongClickListener {
categorizedTasksClickListeners.onLongClickItem(adapterPosition,it)
true
}
binding.executePendingBindings()
}
BindingAdapter function which add stars :
@BindingAdapter("app:setPriority")
fun LinearLayoutCompat.setPriority(task: ToDo) {
if (task.priorityStars == 0)
return
val previousStarContainer = findViewWithTag<LinearLayout>("starContainerLayout")
if (previousStarContainer != null) {
removeView(previousStarContainer)
}
val starContainer = LinearLayout(context)
starContainer.tag = "starContainerLayout"
starContainer.layoutParams = LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
for (count in 1..task.priorityStars) {
val starView = ImageView(context)
starView.setImageResource(R.drawable.task_star)
starView.layoutParams = LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
starContainer.addView(starView)
}
addView(starContainer)
}
Recycler recycle views :) - It uses same view to show multiple data! That means that a view can be used to show an object with stars - so on onBindViewHolder
you show the stars. And then the same view (with stars now) will be used to show a different object (no star object) - it means that on onBindViewHolder
you will now need to hide the stars, which I bet you didn't ;)
As I said, if you have no stars you don't remove the previous starts :
if (task.priorityStars == 0)
return
Change your code to:
@BindingAdapter("app:setPriority")
fun LinearLayoutCompat.setPriority(task: ToDo) {
val previousStarContainer = findViewWithTag<LinearLayout>("starContainerLayout")
if (previousStarContainer != null) {
removeView(previousStarContainer)
}
if (task.priorityStars == 0)
return
val starContainer = LinearLayout(context)
starContainer.tag = "starContainerLayout"
starContainer.layoutParams = LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
for (count in 1..task.priorityStars) {
val starView = ImageView(context)
starView.setImageResource(R.drawable.task_star)
starView.layoutParams = LinearLayoutCompat.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
starContainer.addView(starView)
}
addView(starContainer)
}