diff --git a/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/LibraryGroupAD.kt b/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/LibraryGroupAD.kt index bc28dcb4e..2fb3b9f42 100644 --- a/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/LibraryGroupAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/LibraryGroupAD.kt @@ -48,6 +48,7 @@ fun libraryGroupAD( MangaItemDiffCallback(), mangaGridItemAD(coil, lifecycleOwner, listenerAdapter, sizeResolver), ) + adapter.registerAdapterDataObserver(ScrollKeepObserver(binding.recyclerView)) binding.recyclerView.setRecycledViewPool(sharedPool) binding.recyclerView.adapter = adapter val spacingDecoration = SpacingItemDecoration(context.resources.getDimensionPixelOffset(R.dimen.grid_spacing)) diff --git a/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/ScrollKeepObserver.kt b/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/ScrollKeepObserver.kt new file mode 100644 index 000000000..e15aeec3f --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/library/ui/adapter/ScrollKeepObserver.kt @@ -0,0 +1,31 @@ +package org.koitharu.kotatsu.library.ui.adapter + +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView + +class ScrollKeepObserver( + private val recyclerView: RecyclerView, +) : RecyclerView.AdapterDataObserver() { + + private val layoutManager: LinearLayoutManager + get() = recyclerView.layoutManager as LinearLayoutManager + + override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) { + val position = minOf(toPosition, fromPosition) // if items are swapping positions may be swapped too + if (position < layoutManager.findFirstVisibleItemPosition()) { + postScroll(position) + } + } + + override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { + if (positionStart < layoutManager.findFirstVisibleItemPosition()) { + postScroll(positionStart) + } + } + + private fun postScroll(targetPosition: Int) { + recyclerView.post { + layoutManager.scrollToPositionWithOffset(targetPosition, 0) + } + } +}