'Recyclerview: update view elements outside the screen

I have a recycler view that looks like this:

enter image description here

At the start, these circle icons are empty. I need to update every icon of my recycler to be from empty to full within an interval of 5 seconds (see the image above).

I actually can update these icons, but my problem is: If I have 20 items, I'll need to scroll the recycler in order to see every item. Whenever I scroll the recycler, the last 4-5 items don't get updated from empty to full.

I just need to update the UI, I don't need to remove or add anything to the recyclerview. I've already tried to use notifyDataSetChanged(), notifyItemChanged(), but nothing worked so far. What's your suggestion? Thank you in advance



Solution 1:[1]

Here's one strategy. Have one function in your adapter to start/reset the animation. You can call it when you set the data list. In onBindViewHolder you calculate when relative to now the icon should change to filled (could be in the past). The ViewHolder class either immediately shows the filled icon if the time is negative, or else it posts a delayed runnable to change it in the future. You'll need to cancel any previous delayed runnable so when views get recycled, they always get updated to the correct state.

//Inside your ViewHolder class:
private val setIconRunnable = Runnable { setFilledIcon() }

fun fillIconAt(timeFromNowMillis: Long) {
    itemView.removeCallbacks(setIconRunnable)
    if (timeFromNowMillis <= 0L) {
        setFilledIcon()
    } else {
        setEmptyIcon()
        itemView.postDelayed(setIconRunnable, timeFromNowMillis)
    }
}
// In your adapter class:
companion object {
    private const val ANIMATION_DURATION = 5000L
}

private var animationStartTime = 0L

fun initiateIconAnimation() {
    animationStartTime = System.currentTimeMillis()
    notifyDataSetChanged()
}

override fun onBindViewHolder(holder: YourViewHolderType, position: Int) {
    //...

    val iconChangeTime = (
            ANIMATION_DURATION * (position + 1).toFloat() / yourDataList.size
        ).roundToLong() + animationStartTime
    holder.fillIconAt(iconChangeTime - System.currentTimeMillis())
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tenfour04