Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto scroll recyclerview slider

Tags:

I am new to Android development. I am trying to create an auto scroll recyclerview slider which also supports user events such as next and previous buttons and manual scrolling.

Something like this: enter image description here

I have implemented the recyclerview and buttons events handling but I don't know how to implementing auto scroll, it is only scrolling from position 0 to the end and how to stop the auto scroll if the user swiped the slider manually or clicked on the buttons.

MainActivity.java

public class MainActivity extends AppCompatActivity {

RecyclerView mRecyclerView;
LinearLayoutManager layoutManager;
HorizontalSliderAdapter recyclerAdapter;
Button btnPrev;
Button btnNext;

Runnable runnable;
Handler handler;

public static final String LOGTAG = "slider";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mRecyclerView = (RecyclerView) findViewById(R.id.horizontal_slider_recyclerview);
    setUpRecyclerView();
    autoScroll();

}

public void setUpRecyclerView() {

    final List<HorizontalSliderModel> RowItems = HorizontalSliderModel.getData();
    layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
    mRecyclerView.setLayoutManager(layoutManager);
    mRecyclerView.setHasFixedSize(true);
    recyclerAdapter = new HorizontalSliderAdapter(this, RowItems);
    mRecyclerView.setAdapter(recyclerAdapter);

    btnPrev = (Button) findViewById(R.id.bPrev);
    btnNext = (Button) findViewById(R.id.bNext);

    btnPrev.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mRecyclerView.getLayoutManager().scrollToPosition(layoutManager.findFirstVisibleItemPosition() - 1);
        }
    });
    btnNext.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mRecyclerView.getLayoutManager().scrollToPosition(layoutManager.findLastVisibleItemPosition() + 1);
        }
    });

    mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

            switch (newState) {

                case RecyclerView.SCROLL_STATE_IDLE:

                    float targetBottomPosition1 = mRecyclerView.getX();
                    float targetBottomPosition2 = mRecyclerView.getX() + mRecyclerView.getWidth();

                    Log.i(LOGTAG, "targetBottomPosition1 = " + targetBottomPosition1);
                    Log.i(LOGTAG, "targetBottomPosition2 = " + targetBottomPosition2);

                    View v1 = mRecyclerView.findChildViewUnder(targetBottomPosition1, 0);
                    View v2 = mRecyclerView.findChildViewUnder(targetBottomPosition2, 0);

                    float x1 = targetBottomPosition1;
                    if (v1 != null) {
                        x1 = v1.getX();
                    }

                    float x2 = targetBottomPosition2;
                    if (v2 != null) {
                        x2 = v2.getX();
                    }


                    Log.i(LOGTAG, "x1 = " + x1);
                    Log.i(LOGTAG, "x2 = " + x2);

                    float dx1 = Math.abs(mRecyclerView.getX() - x1);
                    float dx2 = Math.abs(mRecyclerView.getX() + mRecyclerView.getWidth() - x2);


                    Log.i(LOGTAG, "dx1 = " + dx1);
                    Log.i(LOGTAG, "dx2 = " + dx2);

                    float visiblePortionOfItem1 = 0;
                    float visiblePortionOfItem2 = 0;

                    if (x1 < 0 && v1 != null) {
                        visiblePortionOfItem1 = v1.getWidth() - dx1;
                    }

                    if (v2 != null) {
                        visiblePortionOfItem2 = v2.getWidth() - dx2;
                    }

                    Log.i(LOGTAG, "visiblePortionOfItem1 = " + visiblePortionOfItem1);
                    Log.i(LOGTAG, "visiblePortionOfItem2 = " + visiblePortionOfItem2);

                    int position = 0;
                    if (visiblePortionOfItem1 >= visiblePortionOfItem2) {
                        position = mRecyclerView.getChildAdapterPosition(mRecyclerView.findChildViewUnder(targetBottomPosition1, 0));
                    } else {

                        position = mRecyclerView.getChildAdapterPosition(mRecyclerView.findChildViewUnder(targetBottomPosition2, 0));
                    }
                    mRecyclerView.scrollToPosition(position);

                    break;

                case RecyclerView.SCROLL_STATE_DRAGGING:

                    break;

                case RecyclerView.SCROLL_STATE_SETTLING:

                    break;

            }
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        }
    });

}


public void autoScroll() {
    final int speedScroll = 2000;
    handler = new Handler();
    runnable = new Runnable() {
        int count = -1;

        @Override
        public void run() {
            if (count < mRecyclerView.getAdapter().getItemCount()) {
                mRecyclerView.smoothScrollToPosition(++count);
                handler.postDelayed(this, speedScroll);
            }
            if (count == mRecyclerView.getAdapter().getItemCount()) {
                mRecyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(MainActivity.this));
                mRecyclerView.smoothScrollToPosition(--count);
                handler.postDelayed(this, speedScroll);
            }

        }

    };

    handler.post(runnable);
}
}
like image 841
Mays Attari Avatar asked Aug 06 '16 13:08

Mays Attari


People also ask

Does RecyclerView automatically scroll?

To make RecyclerView auto scroll, we have to call smoothScrollToPosition every specified interval of time. We can use Flowable. interval to emit sequential Long value. To stop auto scroll if a user swipes RecyclerView, we can listen to the scroll state change.

How to auto scroll up Recycler view in Android?

You need to scroll the recycler view gradually using the post delay method of the handler. Now you need to initialize your handler. Don't forget to remove the listener in onStop() method and reinitialize at onResume() method. That's all for automatic scroll in recycler view.

How do I know my RecyclerView is scrolling?

You can use Scroll listener to detect scroll up or down changes in RecyclerView . RecycleView invokes the onScrollStateChanged() method before onScrolled() method. The onScrollStateChanged() method provides you the RecycleView's status: SCROLL_STATE_IDLE : No scrolling.


1 Answers

About the auto-scroll, I just started a new master/detail template in Android Studio.

Can you try to use this class as your recyclerView's layout manager ?

public class ScrollingLinearLayoutManager extends LinearLayoutManager {
private final int duration;

public ScrollingLinearLayoutManager(Context context, int orientation, boolean reverseLayout, int duration) {
    super(context, orientation, reverseLayout);
    this.duration = duration;
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
                                   int position) {
    View firstVisibleChild = recyclerView.getChildAt(0);
    int itemHeight = firstVisibleChild.getHeight();
    int currentPosition = recyclerView.getChildLayoutPosition(firstVisibleChild);
    int distanceInPixels = Math.abs((currentPosition - position) * itemHeight);
    if (distanceInPixels == 0) {
        distanceInPixels = (int) Math.abs(firstVisibleChild.getY());
    }
    SmoothScroller smoothScroller = new SmoothScroller(recyclerView.getContext(), distanceInPixels, duration);
    smoothScroller.setTargetPosition(position);
    startSmoothScroll(smoothScroller);
}

private class SmoothScroller extends LinearSmoothScroller {
    private final float distanceInPixels;
    private final float duration;

    public SmoothScroller(Context context, int distanceInPixels, int duration) {
        super(context);
        this.distanceInPixels = distanceInPixels;
        this.duration = duration;
    }

    @Override
    public PointF computeScrollVectorForPosition(int targetPosition) {
        return ScrollingLinearLayoutManager.this
                .computeScrollVectorForPosition(targetPosition);
    }

    @Override
    protected int calculateTimeForScrolling(int dx) {
        float proportion = (float) dx / distanceInPixels;
        return (int) (duration * proportion);
    }
}

}

And set it like this

recyclerView.setAdapter(new SimpleItemRecyclerViewAdapter(DummyContent.ITEMS));
    recyclerView.setLayoutManager(new ScrollingLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false, 5000));

And trigger it this way

recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount());
like image 120
Julien Avatar answered Sep 26 '22 16:09

Julien