Android 在顶部添加新项目后,回收器视图不会滚动到顶部,因为列表适配器尚未发生更改
我将在live data中获取一个新列表,该列表的开头有一个新项目,然后使用它的数据更新适配器Android 在顶部添加新项目后,回收器视图不会滚动到顶部,因为列表适配器尚未发生更改,android,android-recyclerview,kotlin,android-architecture-components,Android,Android Recyclerview,Kotlin,Android Architecture Components,我将在live data中获取一个新列表,该列表的开头有一个新项目,然后使用它的数据更新适配器 viewModel.myLiveData.observe { this, Observer { myList -> adapter.submitList(myList) recyclerView.scrollToPosition(0) } 解决此问题的另一种方法是将Recyclerview包装在嵌套的ScrollView中 <android.supp
viewModel.myLiveData.observe { this, Observer { myList ->
adapter.submitList(myList)
recyclerView.scrollToPosition(0)
}
解决此问题的另一种方法是将Recyclerview包装在嵌套的ScrollView中
<android.support.v4.widget.NestedScrollView
android:id="@+id/nsv_data"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false"
tools:listitem="@layout/rv_interview_prep_row"
android:visibility="gone"
android:background="@color/white" />
</android.support.v4.widget.NestedScrollView>
你也可以使用
recyclerView.smoothScrollToPosition(0);
viewModel.myLiveData.observe { this, Observer { myList ->
adapter.submitList(myList)
recyclerView.smoothScrollToPosition(0);
}
谢谢大家的回复。但对我来说唯一有效的工作是在执行submitList后延迟1秒。尽管不合适,但其工作原理如下:
adapter.submitList()
将始终使用相同的执行时间(毫秒内)
我刚打过电话
Handler().postDelayed ({
recycler.scrollToPosition(0)
}, 1000)
这样
viewModel.myLiveData.observe { this, Observer { myList ->
adapter.submitList(myList) // Assuming you are notifying adapter by notifydatasetchanged()
recyclerView.post { recyclerView.scrollToPosition(0) }
}
这里的
post
给了UI线程一些时间来用新数据填充回收器,然后调用scrollToPosition
submitList
在后台线程上执行其工作,因此总会有延迟无法解决的竞态条件。幸运的是,我们可以使用RecyclerView.AdapterDataObserver
回调在列表计算完成时得到通知:
yourRecyclerViewAdapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() {
override fun onChanged() {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
recycler_view_list.scrollToPosition(0)
}
})
viewModel.myLiveData.observe { this, Observer { myList ->
adapter.submitList(myList)
}
与一秒钟的延迟recyclerView.post{recyclerView.scrollToPosition(0)}相比,这会更好。你可以试试这个。此外,这不会在每次数据更新时创建Handler()。它将队列滚动任务到更新时使用的同一队列RecyclerView。检查我的答案,这样你将节省少量内存(保存创建的每个处理程序)和计算(创建处理程序对象)并且在滚动时几乎没有可见的延迟。如果有帮助,请不要忘记接受并更新答案。某个时间->帖子告诉android,将此工作添加到UI线程工作队列。这并不是“给它一些时间”,这只是你将工作发布到已经在做事情的列表上的副作用。这就是为什么它可能是这样工作的,但是要小心,如果数据很长或者提交列表的diff-util需要更长的时间,这不会总是像您所期望的那样。在嵌套的滚动视图中包装RecyclerView几乎总是一个坏主意。例如,一个不太为人所知的副作用是,recyclerview不能再“循环”视图,因为它不知道可用空间的高度(嵌套的滚动视图必须膨胀所有视图以确定内容的“高度”)。用100行试试这个:没问题。现在用1000试试很好的解决方案,谢谢!但是我必须跳过第一次调用
onItemRangeInserted()
,以避免在旋转时丢失滚动位置。
yourRecyclerViewAdapter.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() {
override fun onChanged() {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
recycler_view_list.scrollToPosition(0)
}
override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
recycler_view_list.scrollToPosition(0)
}
})
viewModel.myLiveData.observe { this, Observer { myList ->
adapter.submitList(myList)
}