I'm implementing a horizontal RecyclerView
that snap items to center after scrolling, like Google play App horizontal lists. This is a review.
My code is below:
MainMenuAdapter mainMenuAdapter = new MainMenuAdapter(this, mDataset);
final LinearLayoutManager layoutManagaer = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView mainMenu = (RecyclerView) findViewById(R.id.main_menu);
mainMenu.setLayoutManager(layoutManagaer);
mainMenu.setAdapter(mainMenuAdapter);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mainMenu);
How I can get the center item (position) after RecyclerView
snapped it to center? Isn't there any listener implementation for this?
Also, when an item view be touched, I want to snap it to center. How can I do this?
Take LinearLayout in your RecyclerView 's item row layout then give android:layout_gravity="center" to LinearLayout . For each row of images you have to take different LinearLayout .
You can now just use a SnapHelper. If you want a center-aligned snapping behavior similar to ViewPager then use PagerSnapHelper: SnapHelper snapHelper = new PagerSnapHelper(); snapHelper. attachToRecyclerView(recyclerView);
SnapHelper is a helper class that helps in snapping any child view of the RecyclerView. For example, you can snap the firstVisibleItem of the RecyclerView as you must have seen in the play store application that the firstVisibleItem will be always completely visible when scrolling comes to the idle position.
SnapHelper is a helper class that is used to snap any child of our RecyclerView. With the help of this class, we can display the specific number of RecyclerView items on our screen, and we can avoid the RecyclerView children's display inside our RecyclerView.
if you need the View, you can call
View view = snapHelper.findSnapView(layoutManagaer);
once you have the View, you should be able to get the position on the dataset for that View. For instance using
mainMenu.getChildAdapterPosition(view)
Better to use this method:
https://medium.com/over-engineering/detecting-snap-changes-with-androids-recyclerview-snaphelper-9e9f5e95c424
Original post:
Even if you are not going to use SnapHelper
you can get the central element position by RecyclerView.OnScrollListener
.
MiddleItemFinder
class to your project.Create callback object MiddleItemCallback
.
MiddleItemFinder.MiddleItemCallback callback =
new MiddleItemFinder.MiddleItemCallback() {
@Override
public void scrollFinished(int middleElement) {
// interaction with middle item
}
};
Add new scroll listener to your RecyclerView
recyclerView.addOnScrollListener(
new MiddleItemFinder(getContext(), layoutManager,
callback, RecyclerView.SCROLL_STATE_IDLE));
The last parameter or MiddleItemFinder
constructor is scrollState
.
RecyclerView.SCROLL_STATE_IDLE
– The RecyclerView is not currently
scrolling. Scroll finished.RecyclerView.SCROLL_STATE_DRAGGING
– The RecyclerView is currently
being dragged by outside input such as user touch input.RecyclerView.SCROLL_STATE_SETTLING
– The RecyclerView is currently
animating to a final position while not under outside control.MiddleItemFinder.ALL_STATES
– All states together.RecyclerView.SCROLL_STATE_IDLE
as the last constructor parameter than in the end of all scroll the callback object will return you the middle element position.public class MiddleItemFinder extends RecyclerView.OnScrollListener {
private
Context context;
private
LinearLayoutManager layoutManager;
private
MiddleItemCallback callback;
private
int controlState;
public
static final int ALL_STATES = 10;
public MiddleItemFinder(Context context, LinearLayoutManager layoutManager, MiddleItemCallback callback, int controlState) {
this.context = context;
this.layoutManager = layoutManager;
this.callback = callback;
this.controlState = controlState;
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (controlState == ALL_STATES || newState == controlState) {
int firstVisible = layoutManager.findFirstVisibleItemPosition();
int lastVisible = layoutManager.findLastVisibleItemPosition();
int itemsCount = lastVisible - firstVisible + 1;
int screenCenter = context.getResources().getDisplayMetrics().widthPixels / 2;
int minCenterOffset = Integer.MAX_VALUE;
int middleItemIndex = 0;
for (int index = 0; index < itemsCount; index++) {
View listItem = layoutManager.getChildAt(index);
if (listItem == null)
return;
int leftOffset = listItem.getLeft();
int rightOffset = listItem.getRight();
int centerOffset = Math.abs(leftOffset - screenCenter) + Math.abs(rightOffset - screenCenter);
if (minCenterOffset > centerOffset) {
minCenterOffset = centerOffset;
middleItemIndex = index + firstVisible;
}
}
callback.scrollFinished(middleItemIndex);
}
}
public interface MiddleItemCallback {
void scrollFinished(int middleElement);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With