'Saving scroll of RecyclerView with navigation component
I'm using the Navigation Component with a BottomNavigationView in my app. It switches between 4 destinations one of which contains a fragment with a RecyclerView containing hundreds of items. When I use the back button the RecyclerView restores with the previous scroll position. But When I use BottomNavigationView to switch between destinations, It won't restore to previous position and resets to the top of RecyclerView. Here's the code I tried to prevent that
override fun onPause() {
super.onPause()
lastScrollPos = linearLayoutManager.findFirstVisibleItemPosition()
}
override fun onResume() {
super.onResume()
card_recyclerView.layoutManager?.scrollToPosition(lastScrollPos)
}
This is not workign what is the best way of restoring RecyclerView to correct position?
Solution 1:[1]
The reason why it does not scroll to the previous position is the navController recreates the fragment (using replace) when used with the bottomNavigation.
A simple approach to save the scroll state is to store the layoutManager state in onDestroyView and restore it on onCreateView unlike the scrollToPosition this approach will scroll to the exact position when the NavController recreates the fragment.
I posted full code in another thread https://stackoverflow.com/a/66940957/2102794
Solution 2:[2]
This can be done by saving the Y-Axis position of the ScrollView in a member variable and restore it in onCreateView(). This works because the member variables are not destroyed.
class DiscoverDataFragment : BaseFragment() {
private var loaded = false
private var scrollPos = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_discover_data, container, false)
}
override fun onCreateBind() {
super.onCreateBind()
if (!loaded) {
// Load views here
loaded = true
}
if (scrollPos > 0) {
scrollDiscoverData.scrollY = scrollPos
}
setScrollListener()
}
private fun setScrollListener() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
scrollDiscoverData.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
scrollPos = scrollY
}
}
}
Solution 3:[3]
you must initialize adapter outside fragment lifecycle, for example
class MyFragment : Fragment() {
private val myViewModel by viewModel<MyViewModel>()
private lateinit var myAdapter : MyAdapter
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
myAdapter = MyAdapter()
Log.d("checkListData", myAdapter.currentList.toString())
myViewModel.someListData.observe(viewLifecycleOwner){ listData ->
myAdapter.submitList(listData)
}
}}
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 | |
| Solution 2 | Elletlar |
| Solution 3 |
