在片段中更新 RecyclerView 时的 scrollToPosition()

scrollToPosition() when updating RecyclerView in a fragment

我制作了一个列表,它使用 LiveData 从房间数据库中获取项目。这个 liveData<List> 然后使用 BindingAdapter 绑定到 recyclerView。 列表适配器是 listAdapter,而不是 `RecyclerView.Adapter.

我需要帮助保持滚动状态或以某种方式返回到 recyclerView 重新加载之前我所在的滚动索引:

//In ViewModel
    val movieList = moviesRepository.movies

..

//in Repo
  val movies: LiveData<List<Movie>> =
    Transformations.map(database.movieDao.getMovies()) {
        it.asDomainModel()
    }

每次数据库更新时,recyclerView 都会回到顶部。

这里是 RecyclerView 和列表的 bindingAdapter

@BindingAdapter("listData")
fun bindRecyclerView(recyclerView: RecyclerView, data: List<Movie>?) {
    val adapter = recyclerView.adapter as MovieListAdapter
    //Log.d("listData binding", "${data}")
    adapter.submitList(data)
}

我想我需要使用类似 的东西 更新发生后,不知道如何在更新发生时自动调用

Project Repo

  1. 首先不要使用ListAdapter RecyclerView有更优化的适配器here

  2. 在您的适配器中提供覆盖项目列表的功能并且您可以在其中通知数据更改

  3. 使用smoothScrollToPosition(lastVisiblePosition)滚动到lastVisiblePosition = layoutManager.findFirstVisibleItemPosition()

  4. 的最后一个可见位置
  5. 在将新项目推送到适配器之前更新 lastVisiblePosition notifyDatasetChanged()

步骤 2

fun updateList(newItems:List<Movie>) {
    moviesList.addAll(newItems)
    lastVisiblePosition = layoutManager.findFirstVisibleItemPosition()
    notifyDataSetChanged()
}

从您的角度来看,当您调用 adapter.updateList(newItems) 时,只需调用 recyclerView.smoothScrollToPosition(adapter.lastVisiblePosition)

明白了。 我能找到的所有示例都使用活动,而不是片段。所以我所要做的就是将其弹出到相关 fragment.kt 文件中的 onCreateView() 函数中。

    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)

            }
        }

这里的binding.movieList指的是这个xml元素

 <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" />