RecyclerView with SnapHelper, item is not snapped after scrollToPosition - android

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

Related

Scroll RecyclerView with current Complete visible item height

I have RecyclerView that contains user post , post height is not fixed , I have attached PagerSnapHelper to this RecyclerView .
How can I make scrolling distance of this RecyclerView with current complete visible item in RecyclerView .
binding.videoTrendsRecycle.setLayoutManager(mLayoutManager);
binding.videoTrendsRecycle.setMediaObjects(videosResponse.getVideosResponseArrayList());
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.findTargetSnapPosition(mLayoutManager, 0, 1000);
binding.videoTrendsRecycle.setOnFlingListener(null);
snapHelper.attachToRecyclerView(binding.videoTrendsRecycle);
VideoPlayerRecyclerAdapter adapter = new VideoPlayerRecyclerAdapter(videosResponse.getVideosResponseArrayList(), initGlide(context), context);

Android - recycler view scroll to position doesn't work

I am trying to retrieve data from firebase then display it in recycler view. I set the layout to be reverselayout = true. However, when I run the activity, the view starts at the bottom. I tried to change the initial position when the application is run using scrollToPosition as commented below, but still nothing changes. Does anyone have a solution related to this problem?
I've tried this: https://stackoverflow.com/a/26876044/7825519
But still start from bottom.
mRecyclerView!!.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
(mRecyclerView!!.layoutManager as LinearLayoutManager).reverseLayout = true
(mRecyclerView!!.layoutManager as LinearLayoutManager).stackFromEnd = true
mRecyclerView?.scrollToPosition(3)
// mRecyclerView?.smoothScrollToPosition(3)
// (mRecyclerView!!.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(3,0)
// mNestedScrollView?.scrollTo(0,3)
mAdapter = DiscoverAdapter(mItems, mPostKey, Static.mLikedPosts, this)
mRecyclerView!!.adapter = mAdapter
val spacingInPixels = resources.getDimensionPixelSize(R.dimen.margin_between_card)
mRecyclerView!!.addItemDecoration(SpacesItemDecoration(spacingInPixels))
First of all delete the both lines that make the recyclerview start from the botom.
Set the scrolling after you set the adapter:
mRecyclerView!!.adapter = mAdapter
mRecyclerView?.scrollToPosition(3)
Try to set scrollToPosition using post method of View

get visible item in RecyclerView

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/')

How to use RecyclerView.scrollToPosition() to move the position to the top of current view?

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

Smoothscroll with RecyclerView put item on bottom of list

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()));

Categories

Resources