Recycler view not scrolling to the top after addin

2020-06-13 12:16发布

问题:

I am getting the new list with new item at the start in my live data and then using its data to update the adapter

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
        recyclerView.scrollToPosition(0)
}

回答1:

submitList does its work on a background thread, so there will always be race conditions that delays can't solve. Fortunately, we can use a RecyclerView.AdapterDataObserver callback to be informed when the list calculations are complete:

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) 
}


回答2:

Use this way

viewModel.myLiveData.observe { this, Observer { myList -> 
    adapter.submitList(myList) // Assuming you are notifying adapter by notifydatasetchanged()
    recyclerView.post { recyclerView.scrollToPosition(0) }
}

Here post is giving UI Thread some time to populate Recycler with new data and then call scrollToPosition.



回答3:

Thank you everyone for response. But the only work that did worked for me was to place a 1 second delay after executing submitList. Even though not appropriate one, But works for the following reason:

adapter.submitList() will always take the same execution time (within milliseconds)

I just called

Handler().postDelayed ({
  recycler.scrollToPosition(0)
}, 1000)


回答4:

You can also use

recyclerView.smoothScrollToPosition(0);

viewModel.myLiveData.observe { this, Observer { myList -> 
        adapter.submitList(myList) 
         recyclerView.smoothScrollToPosition(0);
}


回答5:

Another way to Solve this Problem is wrapping the Recyclerview inside the Nested 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>

Then inside your Activity or Fragment.

viewModel.myLiveData.observe { this, Observer { myList -> 
    adapter.submitList(myList) 
    nestedScrollView.scrollTo(0,0);
}