RecyclerVIew auto scroll to display all the elements as in News Feed etc.,
Asked Answered
D

9

12

How to auto scroll RecyclerView smoothly so that user can see all the elements of the RecyclerView and scroll again from the start - as in News Feed etc.

I know smoothScrollToPosition() and scrollToPosition() but they would just end up scrolling too fast to the last element.

I want the RecyclerView to be animated and move slowly.

Diphyodont answered 3/3, 2016 at 13:48 Comment(1)
Check this Answer with smooth scrollKrug
T
27

Just to improve on the answer a little, it's auto scrolling infinity with smooth animation.

final int speedScroll = 1200;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
    int count = 0;
    boolean flag = true;
    @Override
    public void run() {
        if(count < adapter.getItemCount()){
            if(count==adapter.getItemCount()-1){
                flag = false;
            }else if(count == 0){
                flag = true;
            }
            if(flag) count++;
            else count--;

            recyclerView.smoothScrollToPosition(count);
            handler.postDelayed(this,speedScroll);
        }
    }
};

handler.postDelayed(runnable,speedScroll);

This is exactly your answer but if you link to more smooth animation then use LayoutManager

recyclerView.setLayoutManager(new CustomLinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));

Control you animation changing MILLISECONDS_PER_INCH value.

public class CustomLinearLayoutManager extends LinearLayoutManager {
    public CustomLinearLayoutManager(Context context) {
        super(context);
    }

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

    public CustomLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        final LinearSmoothScroller linearSmoothScroller =
                new LinearSmoothScroller(recyclerView.getContext()) {
                    private static final float MILLISECONDS_PER_INCH = 200f;

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

                    @Override
                    protected float calculateSpeedPerPixel
                            (DisplayMetrics displayMetrics) {
                        return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
                    }
                };
        linearSmoothScroller.setTargetPosition(position);
        startSmoothScroll(linearSmoothScroller);
    }
}
Topographer answered 2/2, 2017 at 8:3 Comment(5)
when I scroll manually. Auto scroll does not continue from that item.Latashialatch
Works perfectly but the slider time is too slow increasing to 3000 ms was perfect.Dunaville
Running in my emulator, it seems that CPU is working hardly. I wonder if battery consumption would be too high.Pannonia
OutOfMemoryError occured.Demivolt
@AbhilashMaurya don't see any memory issue.Topographer
Z
12

I think this is the best solution for this.

    final int speedScroll = 150;
    final Handler handler = new Handler();
    final Runnable runnable = new Runnable() {
        int count = 0;
        @Override
        public void run() {
            if(count < list.size()){
                recyclerView.scrollToPosition(count++);
                handler.postDelayed(this,speedScroll);
            }


        }
    };

    handler.postDelayed(runnable,speedScroll);
Zephyrus answered 3/3, 2016 at 14:9 Comment(3)
how to get the position of card displayed, and increment from it instead of starting againCousteau
This scroll is not smooth. And how to start again and again until activity is running ?Quash
@AliAhmed true, its better to use the LayoutManager for scrolling other than the Recyclerview itselfPedagogics
M
9

This is the best way to Auto Scroll RecyclerView and its 100% working :

  RecyclerView recyclerView = findViewById(R.id.rv_id);

  final int time = 4000; // it's the delay time for sliding between items in recyclerview

    final Adapter adapter = new Adapter(dataItems);
    recyclerView.setAdapter(adapter);

    final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(rootView.getContext(), LinearLayoutManager.HORIZONTAL, false);
    recyclerView.setLayoutManager(linearLayoutManager);

    //The LinearSnapHelper will snap the center of the target child view to the center of the attached RecyclerView , it's optional if you want , you can use it
    final LinearSnapHelper linearSnapHelper = new LinearSnapHelper();
    linearSnapHelper.attachToRecyclerView(recyclerView); 

    final Timer timer = new Timer();
    timer.schedule(new TimerTask() {

        @Override
        public void run() {

            if (linearLayoutManager.findLastCompletelyVisibleItemPosition() < (adapter.getItemCount() - 1)) {

                linearLayoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), linearLayoutManager.findLastCompletelyVisibleItemPosition() + 1);
            }

            else if (linearLayoutManager.findLastCompletelyVisibleItemPosition() == (adapter.getItemCount() - 1)) {

                linearLayoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), 0);
            }
        }
    }, 0, time);
Mutilate answered 3/7, 2019 at 14:29 Comment(0)
R
3

After Trial And Errors This Works Perfect For Me

    final RecyclerView mRecyclerViewr;
    final ArrayList<String> stringArrayData = new ArrayList<String>
    final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.HORIZONTAL, false);
    mRecyclerViewr.setLayoutManager(linearLayoutManager);
    CustomAdapter customAdapter = new CustomAdapter(getApplicationContext(), topPriceBarList);
    mRecyclerViewr.setAdapter(customAdapter);

        // Auto Scroll Left To Right
        final int scrollSpeed = 100;   // Scroll Speed in Milliseconds
        final Handler handler = new Handler();
        final Runnable runnable = new Runnable() {
            int x = 15;        // Pixels To Move/Scroll
            boolean flag = true;
            // Find Scroll Position By Accessing RecyclerView's LinearLayout's Visible Item Position
            int scrollPosition = linearLayoutManager.findLastCompletelyVisibleItemPosition();  
            int arraySize = stringArrayData.size();  // Gets RecyclerView's Adapter's Array Size

            @Override
            public void run() {
                if (scrollPosition < arraySize) {
                    if (scrollPosition == arraySize - 1) {
                        flag = false;
                    } else if (scrollPosition <= 1) {
                        flag = true;
                    }
                    if (!flag) {
                        try {
                            // Delay in Seconds So User Can Completely Read Till Last String
                            TimeUnit.SECONDS.sleep(1); 
                            mRecyclerViewr.scrollToPosition(0);  // Jumps Back Scroll To Start Point
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // Know The Last Visible Item
                    scrollPosition = linearLayoutManager.findLastCompletelyVisibleItemPosition();

                    mRecyclerViewr.smoothScrollBy(x, 0);
                    handler.postDelayed(this, scrollSpeed);
                }
            }
        };
        handler.postDelayed(runnable, scrollSpeed);

This Will Auto Scroll Your RecyclerView To The End, Wait For a Second (So User Can Read Till End) And Jumps/Scroll Back To First String In RecyclerView's Array List. If You Want To Auto Scroll in Posetive And Negative direction You Just Need To Change The Condition Instead Of Using if(!flag) You Need To Set Value Of x in it

    if (flag) x = 15;
    else x= -15;  // For Auto Scroll To Negative i.e Left Direction
Roney answered 4/2, 2018 at 20:23 Comment(1)
using smoothScrollBy disable onClick for items, how to fix thatNaara
H
2
private void hanldeAutoScroll() {


    int position=0;

    final int duration = 2000;
    //final int pixelsToMove = 90;

    final Handler mHandler = new Handler(Looper.getMainLooper());
     final Runnable SCROLLING_RUNNABLE = new Runnable() {

        @Override
        public void run() {

            position++;

            if (position<urls.size())
            {
                recyclerView.scrollToPosition(position);

            }else if (position==urls.size())
            {

                position=-1;

            }

           // recyclerView.smoothScrollBy(pixelsToMove, 0);
            mHandler.postDelayed(this, duration);
        }
    };
    mHandler.postDelayed(SCROLLING_RUNNABLE, 2000);




}
Herrera answered 18/12, 2019 at 9:7 Comment(1)
Use smoothScrollToPosition rather than scrollToPosition for better scrolling like animation.Communicative
S
1

Simplified in Kotlin:

 lifecycleScope.launch(Dispatchers.Main, start = CoroutineStart.DEFAULT) {
        var position = MINIMUM_POSITION
        repeat(AUTO_SCROLL_REPEATING_TIMES) {
            delay(SCROLL_DELAY)
            rvBanners.smoothScrollToPosition(position)
            when {
                position+1 == listSize -> position = 0
                position == 0 -> position = MINIMUM_POSITION
                else -> position++
            }
        }
    }

If you want to start the auto-scroll at a specific time:

val job = lifecycleScope.launch(Dispatchers.Main, start = CoroutineStart.LAZY) {
        var position = MINIMUM_POSITION
        repeat(AUTO_SCROLL_REPEATING_TIMES) {
            delay(SCROLL_DELAY)
            rvBanners.smoothScrollToPosition(position)
            when {
                position+1 == listSize -> position = 0
                position == 0 -> position = MINIMUM_POSITION
                else -> position++
            }
        }
    }
...
job.start()
Sideburns answered 30/8, 2019 at 22:51 Comment(0)
K
0

You can also implement it in this way, after setting recyclerview to adapter

final int duration = 10;
final int pixelsToMove = 263;
final Handler mHandler = new Handler(Looper.getMainLooper());

final Runnable SCROLLING_RUNNABLE = new Runnable() {
        @Override
        public void run() {
            recyclerView.smoothScrollBy(pixelsToMove, 0);
            mHandler.postDelayed(this, duration);
        }
    };

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            int lastItem = horizontalLayoutManager.findLastCompletelyVisibleItemPosition();
            if (lastItem == horizontalLayoutManager.getItemCount() - 1) {
                mHandler.removeCallbacks(SCROLLING_RUNNABLE);
                Handler postHandler = new Handler();
                postHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        quickTips.setAdapter(null);
                        quickTips.setAdapter(adapter);
                        mHandler.postDelayed(SCROLLING_RUNNABLE, 2000);
                    }
                }, 2000);
            }
        }
    });
    mHandler.postDelayed(SCROLLING_RUNNABLE, 2000);
Krug answered 20/3, 2019 at 8:15 Comment(0)
P
0

For Smooth Auto Scrolling you can use this custom RecyclerView Class, where you can also set the scrolling time.

public class AutoScrollRecyclerView extends RecyclerView {
    private static long delayTime = 45;// How long after the interval to perform scrolling
    AutoPollTask autoPollTask;// Scroll thread
    private boolean running; // Is it rolling?
    private boolean canRun;// Can it be automatically scrolled, depending on whether the data exceeds the screen

    public AutoScrollRecyclerView(Context context) {
        super(context);
    }

    public AutoScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        autoPollTask = new AutoPollTask(this);// Instantiate the scroll refresh thread
    }

    static class AutoPollTask implements Runnable {
        private final WeakReference<AutoScrollRecyclerView> mReference;

        // Use weak references to hold external class references to prevent memory leaks
        public AutoPollTask(AutoScrollRecyclerView reference) {
            this.mReference = new WeakReference<>(reference);
        }

        @Override
        public void run() {
            AutoScrollRecyclerView recyclerView = mReference.get();// Get the recyclerview object
            if (recyclerView != null && recyclerView.running && recyclerView.canRun) {
                recyclerView.scrollBy(2, 2);// Note the difference between scrollBy and scrollTo
                //delayed to send
                recyclerView.postDelayed(recyclerView.autoPollTask, delayTime);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                /*if (running)
                    stop();*/
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
                /*if (canRun)
                    start();*/
                break;
        }
        return super.onTouchEvent(e);
    }

    //Open: If it is running, stop first -> then open
    public void start() {
        if (running)
            stop();
        canRun = true;
        running = true;
        postDelayed(autoPollTask, delayTime);
    }
    
    public void stop() {
        running = false;
        removeCallbacks(autoPollTask);
    }
}
Personalize answered 15/7, 2021 at 10:49 Comment(0)
V
0

This Answer is Aware Of Activity/Fragment Lifecycle and this is important below answer is used by taking notes of other answres:

Using Kotlin:

private lateinit var layoutManager:LinearLayoutManager

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {

    layoutManager =  LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)

    binding.autoScrollingRecyclerViewId.layoutManager = layoutManager 

    runSlideShow() // <= auto sliding effect function

    return binding.root
}

> Slide Show Effect:

private fun runSlideShow(){
    
    lifecycleScope.launch {

        while(isActive) {

            if (layoutManager.findLastCompletelyVisibleItemPosition() < (restaurantsAdapter?.itemCount ?:0)  - 1)
             {
                layoutManager.smoothScrollToPosition(
                    binding.autoScrollingRecyclerViewId,
                    RecyclerView.State(),
                    layoutManager.findLastCompletelyVisibleItemPosition() + 1
                )
            } else if (layoutManager.findLastCompletelyVisibleItemPosition() == (restaurantsAdapter?.itemCount ?:0) - 1) {
                layoutManager.smoothScrollToPosition(
                    binding.autoScrollingRecyclerViewId,
                    RecyclerView.State(),
                    0
                )
            }
            delay(6000)
        }
    }
}
Vitia answered 14/11, 2023 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.