I have Recycler View (inside SwipeRefreshLayout) with vertical scrollbar with custom thumb color:
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/messages_swipe_refresh"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/type_message_edit_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/rosters_end_guideline"
app:layout_constraintTop_toTopOf="parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/messages_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:scrollbarThumbVertical="@color/orange"
android:fadeScrollbars="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:stackFromEnd="true" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
In Recycler View I display text messages. I need to display how much time ago message was sent/received, so I store timestamps in recycler's dto:
data class MessageRecyclerDto(
val sendTs: Long,
...
)
I subtract timestamp from current time in onBindViewHolder method to calculate how much time has passed and refresh recycler data each minute, to display updated text:
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(getItem(position))
}
class ViewHolder(
private val binding: RecyclerItemChatMessageBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(dto: MessageRecyclerDto) {
val minutesAgoText = (System.currentTimeMillis() - sendTs).millisToMinutes().toString()
binding.timeAgoTv.text = minutesAgoText binding.executePendingBindings()
}
}
The problem is each time I call notifyItemRangeChanged or notifyDataSetChanged method of the adapter, scrollbars in recycler view appear for a moment and then fade after a while. That's the default behaviour on scroll action. What's more, I have another recycler view in the same Fragment, and scrollbars also appear in it. Recycler Views are not related, they have different adapters.
I don't want to hide scrollbars completely or show them all the time. Is there any way to disable this behaviour? Or maybe someone has some other solution to display elapsed time in Recycler View and refresh it periodically.
if you want scrollbars show only when user drag the list you should do it manually (disable/enable scrollbars).
you need to add addOnScrollListener
and detect scroll to enable scrollbars also before notifyDataSetChanged
disable scrollbars. something like this:
messagesRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
// Check if the user has scrolled the RecyclerView
if (dy != 0) {
// Show the vertical scrollbar
recyclerView.isVerticalScrollBarEnabled = true
}
}
})
and disable it before call changes:
recyclerView.isVerticalScrollBarEnabled = false
adapter.notifyDataSetChanged()