Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start my RecyclerView Horizontal Carousel from the center item

I'm creating a carousel Horizontal RecyclerView with Zoom on focused item that is starting from the first item of the RecyclerView.

Code for custom CenterZoomLayoutManager:

public class CenterZoomLayoutManager extends LinearLayoutManager {
private final float mShrinkAmount = 0.15f;
private final float mShrinkDistance = 0.9f;

public CenterZoomLayoutManager(Context context, int orientation, boolean reverseLayout) {
    super(context, orientation, reverseLayout);
}

@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
    int orientation = getOrientation();
    if (orientation == HORIZONTAL) {

        int scrolled = super.scrollHorizontallyBy(dx, recycler, state);
        float midpoint = getWidth() / 2.f;
        float d0 = 0.f;
        float d1 = mShrinkDistance * midpoint;
        float s0 = 1.f;
        float s1 = 1.f - mShrinkAmount;
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            float childMidpoint =
                    (getDecoratedRight(child) + getDecoratedLeft(child)) / 2.f;
            float d = Math.min(d1, Math.abs(midpoint - childMidpoint));
            float scale = s0 + (s1 - s0) * (d - d0) / (d1 - d0);
            child.setScaleX(scale);
            child.setScaleY(scale);
        }
        return scrolled;
    } else return 0;
}

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    super.onLayoutChildren(recycler, state);
    scrollHorizontallyBy(0, recycler, state);
}
}

And in my Fragment, I have the following:

private void onSetRecyclerView() {

    recyclerView = fragmentView.findViewById(R.id.recyclerView);

    if (recyclerView != null) {
        RecyclerView.LayoutManager layoutManager = new CenterZoomLayoutManager(context, LinearLayoutManager.HORIZONTAL,
                false);

        recyclerView.scrollToPosition(storeList.size() / 2);

        final SnapHelper snapHelper = new LinearSnapHelper();
        snapHelper.attachToRecyclerView(recyclerView);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }
}

I want to start my RecyclerView from the center item and not from the start position.

Culprit:
in my CenterZoomLayoutManager, I'm setting the pixel offset start to 0 pixels through scrollHorizontallyBy(0, recycler, state).

Problem:
I cannot find a way to pass the offset pixels created by recyclerView.scrollToPosition(storeList.size() / 2) to the CenterZoomLayoutManager. I tried to search for different built-in method to get the X-offset, but so far no luck.

like image 970
Red M Avatar asked Sep 13 '18 16:09

Red M


1 Answers

The solution is to change the timing of when LinearSnapHelper is attached to the RecyclerView. The following is a reworked onSetRecyclerView() that will snap the central item of the RecyclerView to the center of the screen. Notice that the LinearSnapHelper is not attached until the RecyclerView is laid out and scrolled appropriately. You do not need to do any scrolling in onLayoutChildren().

private void onSetRecyclerView() {
    recyclerView = findViewById(R.id.recyclerView);
    CenterZoomLayoutManager layoutManager =
        new CenterZoomLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);
    // Scroll to the position we want to snap to
    layoutManager.scrollToPosition(storeList.size() / 2);
    // Wait until the RecyclerView is laid out.
    recyclerView.post(new Runnable() {
        @Override
        public void run() {
            // Shift the view to snap  near the center of the screen.
            // This does not have to be precise.
            int dx = (recyclerView.getWidth() - recyclerView.getChildAt(0).getWidth()) / 2;
            recyclerView.scrollBy(-dx, 0);
            // Assign the LinearSnapHelper that will initially snap the near-center view.
            LinearSnapHelper snapHelper = new LinearSnapHelper();
            snapHelper.attachToRecyclerView(recyclerView);
        }
    });
}

This is how the initial screen of my test app is displayed. There are 201 "stores."

enter image description here

like image 185
Cheticamp Avatar answered Nov 04 '22 17:11

Cheticamp