Reputation: 113
I've made a list which gets items from a Room-database using LiveData
. This liveData<List>
is then bound to a recyclerView
, using a BindingAdapter
.
The lists adapter is listAdapter
, not `RecyclerView.Adapter.
I need help holding onto the scroll-state or somehow returning to the scroll-index I was at before the recyclerView
reloaded:
//In ViewModel
val movieList = moviesRepository.movies
..
//in Repo
val movies: LiveData<List<Movie>> =
Transformations.map(database.movieDao.getMovies()) {
it.asDomainModel()
}
Every time the DB updates, the recyclerView
shoots back up to the top.
And here's the bindingAdapter
for the RecyclerView
and the list.
@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView, data: List<Movie>?) {
val adapter = recyclerView.adapter as MovieListAdapter
//Log.d("listData binding", "${data}")
adapter.submitList(data)
}
I think I need to use something like recyclerView.smoothScrollToPosition(la.getItemCount());
after the update has occured, but I don't know how to automatically call it when the update has occured
Upvotes: 1
Views: 1789
Reputation: 113
figured it out. All of the examples I could find were using Activities, not fragments. So all I had to do was pop this into the onCreateView() function in the relevant fragment.kt file.
binding.movieList.layoutManager =
object : LinearLayoutManager(getActivity(), VERTICAL, false) {
override fun onLayoutCompleted(state: RecyclerView.State) {
super.onLayoutCompleted(state)
val lastVisibleItemPosition = findLastVisibleItemPosition()
val count = (binding.movieList.adapter as MovieListAdapter).itemCount
//speed the scroll up a bit, but make it look smooth at the end
binding.movieList.scrollToPosition(count - 5)
binding.movieList.smoothScrollToPosition(count)
}
}
here, the binding.movieList
is referring to this xml element
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/movie_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toTopOf="@+id/load_more_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:listData="@{viewModel.movieList}"
tools:listitem="@layout/movie_list_item" />
Upvotes: 0
Reputation: 2824
First of all don't use ListAdapter
RecyclerView
has a more optimized adapter here
in your adapter provide a function that overrides the item list and there is where you notify the data change
Use smoothScrollToPosition(lastVisiblePosition)
to scroll to the last visible position where lastVisiblePosition = layoutManager.findFirstVisibleItemPosition()
Update lastVisiblePosition
before you push new items to the adapter notifyDatasetChanged()
Step 2
fun updateList(newItems:List<Movie>) {
moviesList.addAll(newItems)
lastVisiblePosition = layoutManager.findFirstVisibleItemPosition()
notifyDataSetChanged()
}
from your view when you call adapter.updateList(newItems)
just call recyclerView.smoothScrollToPosition(adapter.lastVisiblePosition)
Upvotes: 1