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()));
Related
I have a recyclerview with several items. I need to show the items starting from bottom i.e. first item should be displayed at bottom and after scrolling from bottom to top, further items will get displayed.
For this what I tried is,
linearlayoutManager.setStackFromEnd(true);
This helped to start the items from bottom. But when there are several items, more than the size to fit into the screen at the same time then the first item goes moving at the top as the item count increases.
I also tried with
linearlayoutManager.scrollToPosition(0);
This didn't change anything.
Here is an image showing what I am looking for.
There are few more items in the list above which are still not visible.
Here how it looks When these items are scrolled,
.
I have checked view hierarchy of this view in the image which only shows a recyclerview and the items within it. And the recyclerview's height is match_parent i.e. the top space with no items showing another view underneath of the recyclerview which is a google map.
I just need to know how I can achieve this feature of the recyclerview without using more extra views.
Any help would be greatly appreciated..!!
Try to init your Linear layout as follow
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, true);
The third boolean indicates that it should reverse the items or not.
But remember that your datas should be sorted from newest to oldest also.
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, true);
linearLayoutManager.setStackFromEnd(true);
linearLayoutManager.setReverseLayout(true);
Then once your data is populated
adapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
#Override
public void run() {
recyclerView.smoothScrollToPosition(0);
}
});
Try using a reversed LinearLayoutManager:
LinearLayoutManager linearlayoutManager = new LinearLayoutManager(context, VERTICAL, true);
write this line in xml to start list from bottom
android:stackFromBottom="true"
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stackFromBottom="true">
</android.support.v7.widget.RecyclerView>
and second thing reverse your array list before add in adapter
Add these attributes to your recyclerview (XML)
android:paddingTop="500dp"
android:clipToPadding="false"
You can also set it in the code like this:
recyclerView.setPadding(0, 500, 0, 0);
recyclerView.setClipToPadding(false);
This is for different screen sizes
int height = recyclerView.getHeight()
recyclerView.setPadding(0, height - 200, 0, 0);
recyclerView.setClipToPadding(false);
If you don't know how to get screen width, height and convert dp to px
so here are the links: How to get screen width and height and Converting pixels to dp
Seems like what you want is to have a separate view type in your recycler adapter that doesn't show anything but is the height of the map. This would allow you to 'scroll up' from the bottom where the list starts and continue seeing different views.
A simple example:
public class ScreenBottomRecyclerAdapter extends RecyclerView.Adapter {
final int VIEW_TYPE_MAP = 0;
final int VIEW_TYPE_ROW = 1;
#Override
public int getItemCount() {
return dataset.length + 1;
}
#Override
public int getItemViewType(int position) {
if (position == 0) {
return VIEW_TYPE_MAP;
} else {
return VIEW_TYPE_ROW;
}
}
#Override
public RecyclerView.ViewHolder createViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_MAP: return new ViewHolder(null); // This is an empty recycler row so you can see and interact with the map, it will need to be the height of the map so you'll probably want to make a new view type that the same height but doesn't show anything and doesn't intercept touches
case VIEW_TYPE_ROW: return new RowViewHolder(someInflatedView); // This will be the rows you are already creating
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case VIEW_TYPE_ROW: holder.update(position - 1) // Do your normal update here, but remember that your data will be off by 1 for the map view row in the recycler
}
}
}
Use below code to reverse list:
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity(), RecyclerView.VERTICAL, false);
Important: Set layout manager which have property reverse layout to true
layoutManager.setReverseLayout(true);
RecyclerView.setLayoutManager(layoutManager);
This code will display reverse list which you may have assigned to RecyclerView
I have a RecyclerView in my activity and a LinearSnapHelper attached to it:
TimePickerAdapter timePickerAdapter = new TimePickerAdapter(hours);
recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
The problem is that when I want to initially scroll to a specific item, the snap helper is not being triggered to attach the item (see the image):
recyclerView.getLayoutManager().scrollToPosition(timePickerAdapter.getCurrentPosition());
When I scroll with my hand it starts to work as expected.
Any solutions to this?
SnapHelper rely on RecyclerView.OnFlingListener#onFling() or RecyclerView.OnScrollListener#onScrollStateChanged(recyclerView, RecyclerView.SCROLL_STATE_IDLE) to trigger snap action.
But scrollToPosition() will not tigger above callback. You can invoke smoothScrollBy(1, 0) after scrollToPosition() to trigger SnapHelper to scroll.
I just encountered the same issue - for me using recyclerView.smoothScrollToPosition(pos) instead of recyclerView.scrollToPosition(pos) did the trick
If items have the same width and space between them also the same you can use this for initial scroll
recyclerView.apply {
post {
val dx = initialPosition * (itemWidth + itemSpace)
scrollBy(dx, 0)
}
}
I want to be able to automatically scroll inside an horizontal RecyclerView and put the selected item in middle of the screen
In the attached image the selected item is "my apps" so i want to automatically scroll the RV so that "my apps" will show on center of screen
I know How to scroll to speciffic position:
linearLayoutManager.scrollToPositionWithOffset(2, 20);
How can i get the relative position of the item inside the recyclerView so i can scroll to it?
My RecyclerView def:
CategoriesAdapter adapter = new CategoriesAdapter(list, this);
catagoriesRV.setAdapter(adapter);
LinearLayoutManager llm = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
catagoriesRV.setLayoutManager(llm);
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