I have 3 buttons and a Recyclerview. On click of each button, I am updating the Recyclerview list. I am using the following way to update the Recyclerview list:
fun updateList(list: List<SortFilterItem>){
itemList.clear()
itemList.addAll(list)
notifyDataSetChanged()
}
The problem is if I scroll the list to a certain position and then click on any of the Button the list is updated but the position is not reset to the start position. How can I reset the position of the Recyclerview when I update the list.
LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
layoutManager.scrollToPositionWithOffset(0, 0); //Way I
layoutManager.smoothScrollToPosition(mRecyclerView, null, 0); //Way II
Try yourLayourManager.scrollToPositionWithOffset(0,0), this will scroll until satisfy the offset.
or recyclerView.smoothScrollToPosition(position)
just add line into your button click when you update your code
recyclerView.scrollToPosition(0);
Related
I have a Fragment with a RecyclerView. It works as a chat.
I request to my backend the last 50 messages and I load them in the recycler view
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(layoutManager);
mAdapter = new ChatMessagesAdapter(recyclerView, messages, getActivity());
recyclerView.setAdapter(mAdapter);
recyclerView.getLayoutManager().scrollToPosition(messages.size()-1);
mAdapter.notifyDataSetChanged();
Then, when I scroll up I request more messages with OnScrollListener and I load them
messages.addAll(0, oldMessages);
mAdapter.notifyDataSetChanged();
mAdapter.setLoaded();
recyclerView.getLayoutManager().scrollToPosition((oldMessages.size()) -1);
But as I set the the recyclerView in the first load with
layoutManager.setStackFromEnd(true);
when I load the old messages the scroll moves first item shown(before the last) to the bottom.
How can I add old messages on top and continue the scrolling like if the items were there from the first load? Without move the focus to the bottom
Use notifyItemRangeInserted instead of notifyDataSetChanged.
Use below code to update your adapter:
public void addList(List<ChatMessage> items) {
chatMessages.addAll(0, items);
notifyItemRangeInserted(0,items.size());
notifyItemChanged(items.size());//Only To update the last top item cause in my case it was the date header so i need to notify it
}
How can I get a current item in RecycerView? In my use-case RV item takes all screen space, so there is only one item at a time.
I've tried to google before, but nothing helpful was found.
The whole use case:
UI. The bottom navigation has a button that should call a certain method (let's say a foo() method) in fragment
this foo() method should get a visible item from the adapter and call a specific method in a presenter.
use this in your code
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
and get your visible item using below code
mLayoutManager.findFirstVisibleItemPosition();
You could also use an OnItemClickListener on your RecyclerView's ListAdapter to determine the current item. In that case the item needs to be clicked though.
My solution
val position = (recyclerView?.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val product = adapter?.getItemByPosition(position)
FirebaseCrash.logcat(Log.DEBUG, TAG, "onNavClickEvent = $product")
product?.let { productListViewModel?.order(it.id) }
The result is:
onNavClickEvent = Product(id=1, title='Cap', description='some descr.', price=10, photo='http://lorempixel.com/200/200/sports/1/')
I'm creating an app with a list of questions in a RecyclerView. In the same parent layout, I have a static TextView above the RecyclerView that displays instruction for a set of questions. What I want is to change the text in the TextView whenever a specific question reaches the top of the RecyclerView when scrolled. How can I accomplish this?
You would need to listen to the scrolling of your RecyclerView and get the first item displayed onto the screen.
Thanksfully, Android let us set a custom ScrollListener to a RecyclerView and with your LayoutManager you are able to know which item is shown first :
// initialize your RecyclerView and your LayoutManager
mLinearLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setLayoutManager(mLinearLayoutManager);
// set a custom ScrollListner to your RecyclerView
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
// Get the first visible item
int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
//Now you can use this index to manipulate your TextView
}
});
EDIT : added Mateus Gondim clearance about the LayoutManager
You should override the default Recycler.OnScrollListener.
Have a look at this Code : https://gist.github.com/mipreamble/b6d4b3d65b0b4775a22e
The RecyclerView.scrollToPosition() is extremely strange.
for example, supposed a RecyclerView named "rv".
if now item 10 is under the current RecyclerView, call rv.scrollToPosition(10), the RecyclerView will scroll item 10 to bottom.
if now item 10 is in the current RecyclerView, call rv.scrollToPosition(10), there won't be any scrolling, nothing will be done.
if now item 10 is on the top of the current RecyclerView, call rv.scrollToPosition(10), the RecyclerView will scroll item 10 to top.
To help understanding, look at this picture
But what i need is that, whenever i call it, the RecyclerView will scroll the supposed position to the top of current view just like case 3. How to do that?
If I understand the question, you want to scroll to a specific position but that position is the adapter's position and not the RecyclerView's item position.
You can only achieve this through the LayoutManager.
Do something like:
rv.getLayoutManager().scrollToPosition(youPositionInTheAdapter).
Below link might solve your problem:
https://stackoverflow.com/a/43505830/4849554
Just create a SmoothScroller with the preference SNAP_TO_START:
RecyclerView.SmoothScroller smoothScroller = new
LinearSmoothScroller(context) {
#Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
Now you set the position where you want to scroll to:
smoothScroller.setTargetPosition(position);
And pass that SmoothScroller to the LayoutManager:
layoutManager.startSmoothScroll(smoothScroller);
If you want to scroll to a specific position and that position is the adapter's position, then you can use StaggeredGridLayoutManager scrollToPosition
StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
staggeredGridLayoutManager.scrollToPosition(10);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
This is the Kotlin code snippet but you can just get the point for scrolling to the item by position properly. The point is to declare the member variable for the layout manager and use its method to scroll.
lateinit var layoutManager: LinearLayoutManager
fun setupView() {
...
layoutManager = LinearLayoutManager(applicationContext)
mainRecyclerView.layoutManager = layoutManager
...
}
fun moveToPosition(position: Int) {
layoutManager.scrollToPositionWithOffset(position, 0)
}
try recycler_view.smoothScrollBy(0, 100); here 0 represents x-coordinate and 100 represents y-coordinate I used this in vertical recyclerView where I wanted to scroll to next position in the vertical list and for coming to the previous position I simply replaced 100 with -100
I want the user to be able to navigate to certain positions within a RecyclerView. I can determine the position of the items and when I use recycleView.smoothScrollToPosition() it scrolls to the correct item.
The problem is this item is at the bottom of the screen. How can I scroll so that the item appears at the top (it must be the first visible item).
Here is the code I use to setup the RecyclerView:
recyclerView = (RecyclerView)findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(false);
recyclerView.setAdapter(actionAdapter);
final LinearLayoutManager layoutManager = new LinearLayoutManager(InteractionTimelineActivity.this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setOnScrollListener(new RecyclerScrollListner());
And this is how I scroll:
if (recycleView != null) {
recycleView.smoothScrollToPosition(position + 1);
}
You have to calculate how many items fit on one screen and use that as offset when you scroll! You can use the methods findFirstCompletelyVisibleItemPosition() and findLastCompletelyVisibleItemPosition() of the LayoutManager to calculate the offset like this:
int offset = getLayoutManager()).findLastCompletelyVisibleItemPosition()
- getLayoutManager()).findFirstCompletelyVisibleItemPosition();
And once you have the offset you can scroll like this:
recycleView.smoothScrollToPosition(Math.min(position + offset + 1, adapter.getItemCount()));