I'm trying to programatically scroll to an item in my RecyclerView based on position.
The following code works when scrolling to an item in the RecyclerView adapters data if the position is visible on screen / rendered:
recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
However if I set a position to a value which is not yet visible on the screen / rendered, the page is only scrolled just below the last item which is visible / already rendered. E.g. it works for the first 4 items which are visible, but not the 4 which are off screen.
For extra details the data in the adapter is set in an onSuccess callback:
// update the data in the adapter after hitting a REST API
adapter.updateItems(data);
adapter.notifyDataSetChanged();
// then I scroll to the position
recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
Other methods to invoke the scrolling haven't worked - e.g. just calling recyclerView.scrollToPosition(position)
And the view is rendered inside a BottomSheetDialog.
There seem to be quite a few questions relating to similar things which have not solved my problems - eg RecyclerView - How to smooth scroll to top of item on a certain position?
UPDATE
Actually trying it with a different longer data set its not only the fact that the item position is not visible - it appears to only be the last items which don't scroll correctly (e.g the last three).
Thanks!
Related
I am using a RecyclerView to load some Messages. Calling scrollToPosition(messagesList.size() - 1) the view always loads to the end of the list.
My problem: I would like to add an offset to the scroll position so that new messages are not shown immediately but the user has to scroll down.
Meaning if i have 3 new Messages i would like to have an offset of 3 messages from the bottom.
The method scrollToPosition() seems to use the top of the view as reference point. Is there a way to load list items with an item offset from the botton?
Thanks for your help!
The method scrollToPosition() seems to use the top of the view as
reference point. Is there a way to load list items with an item offset
from the botton?
The best way to create Chat Message list screen with RecyclerView by set
reverseLayout = true to make the messages list displaying from the bottom.
recyclerview.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, true));
And you don't need to call scrollToPosition(messagesList.size() - 1) to scroll to the bottom anytime you have new message. When you scroll to top now with reverseLayout = true is like you scroll the the bottom as your way above.
I have a list of elements in a recycler view that are generated dynamically using data binding. Each element has a bottom view that is initially set to View.GONE, however once a user clicks the element and the view is expanded, the recycler view automatically scrolls back to the top of the list. Conversely, if the view is expanded and then clicked again to collapse, the recycler view scrolls to the top of the list again. I have tried keeping track of the ID's of the elements for the adapter (again using data binding), setting focus to the child element when they expand or collapse, and using binding adapters to animate the expand/collapse itself.
My suspicion is that the adapter in the recycler view is receiving a onNotifyDataChanged() alert when the height of one of the child changes, rendering an additional view (still inside one of the children though, not a separate child in the list), and automatically scrolls to the top. Is there a way to override this? Does anyone know what else might be causing the list to snap to the top when one of the elements is clicked -> expanded/collapsed?
So I found the solution to my issue in case someone encounters something similar. I actually ended up finding this answer: RecyclerView notifyDataSetChanged scrolls to top position
and the second solution involving the staggered layout manager was the route I went with, since I want to be able to wrap the content. My suspicions were correct that it had to do with the changing height of the elements in the recycler view. The expandable item's parent wrapped content, so the recycler view was forced to recalculate the size of the item once the expandable portion appeared/disappeared (at least that's what I got out of it).
I want to scroll a list view by x pixels
list.scrollListBy(x) works, but the default scrolling animations are missing
Is there any api to scroll list with animation,
I cannot use smoothScrollBy and its other varients, because it wont scroll if the element is already visible.
If you are using RecyclerView, you can call the method
list.scrollToPosition(int position)
to scroll to a particular position on the list. Let's say there are 50 positions on the list, and your phone screen is showing first 10 positions of the list. Then you can call
list.scrollToPosition(40);
to scroll to the 40th position. There will be a slightly smooth effect.
I have tried RecyclerView.smoothScrollToPosition(int position), but it's not what I want. It scrolls to a position so that the child get into the viewport; it can either appear at the beginning or the end. Moreover, if the view is already in the viewport, it won't do anything!
What I need to do is to scroll to a position and make it appear at very beginning of RecyclerView so as to arouse user's attention. How can I do with it?
You can use mRecyclerView.scrollToPosition(Position); to display the list item at top. However it will go to the specified position very quickly without any scrolling effect.
I have a ListView which has overlayed on top of it another view which I call a Header. This header can be of various heights.
On ListView's dataset, I insert in a blank row, and programmatically set the height of this row to be the height of my Header view. This way when the ListView loads, the row at position 1 (the actual first row of data) is lined up to the bottom of the header. I do this so I can set the Header view as partially transparent and when the user scrolls they see the rows of data mix with the transparency of the Header view.
Now I have one use case where I can navigate to this list and a given row will be selected. What I've done is call setSelection with position X. This will automatically scroll my ListView so that the top of row X is at the top of the list. However, my Header view still obscures this. To compensate I call scrollTo. These two pieces are something as such:
listView.setSelection(selectedRowPosition);
if(hasHeadersEnabled()) {
listView.scrollTo(-headerView.getMeasuredHeight).
}
When I call these lines of code, my ListView looks as I would expect. The selected row's top is to the bottom of my HeaderView. The problem I run into is that as soon as a user touches the ListView, the scroll position jumps so that the selected row's top is at the true top of the ListView (aka the Header view's top).
My question is, after you setSelectedRow on a ListView, does the ListView always expect that row's top to be the ListView's top when it starts consuming the onTouch events for scrolling? Is there another way to accomplish what I'm hoping to do with this code? I've tried scrollTo and scrollBy and both have the same effect.
So I should have looked at the API harder. Found the answer to my question.
I need to use setSelectionFromTop instead of the combination of setSelection and scrollTo. Here is the sample code:
listView.setSelectionFromTop(rowPosition, headerView.getMeasuredHeight());