54

I am using Recyclerview with CardView. I am aware how to control speed on list view. But not for Recyclerview.

I searched a lot in found class name SmoothScroll. How to use that? I have no Idea! Right now Recyclerview by default scroll is fast.

UPDATE:

I Summarized Gil Answer with this

10
  • @XaverKapeller I want to implement Slow scrolling in RecyclerView. Commented Mar 2, 2015 at 5:54
  • What do you mean with slow scrolling? Please explain more. Do you want to programmatically scroll to some other position? Commented Mar 2, 2015 at 5:56
  • Still don't understand. What scrolling speed? What are you talking about? The scrolling speed when you programmatically scroll to another position? Commented Mar 2, 2015 at 6:22
  • My RecyclerView is endless with Items (Near about 10000 Item). When user scrolls RecyclerView Its scrolling like a wind unable to see Items. So my idea is to slow down speed of scrolling. I hope Now you get What I am trying to say. Commented Mar 2, 2015 at 6:47
  • So you mean when the user flings the RecyclerView or what? Commented Mar 2, 2015 at 16:46

4 Answers 4

112
+50

It's unclear what you mean when you say "smoothScroll". You could be referring to the automatic "smoothScrollToPosition" which will automatically scroll to a specified position, you could be talking about manual scrolling and you could be talking about flinging. For the sake of prosperity, I will attempt to answer all of these issues now.

1. Automatic smooth scrolling.

Inside your layout manager, you need to implement the smoothScrollToPosition method:

 @Override public void smoothScrollToPosition(RecyclerView recyclerView, State state, int position) { // A good idea would be to create this instance in some initialization method, and just set the target position in this method. LinearSmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) { @Override public PointF computeScrollVectorForPosition(int targetPosition) { int yDelta = calculateCurrentDistanceToPosition(targetPosition); return new PointF(0, yDelta); } // This is the important method. This code will return the amount of time it takes to scroll 1 pixel. // This code will request X milliseconds for every Y DP units. @Override protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return X / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, Y, displayMetrics); } }; smoothScroller.setTargetPosition(position); startSmoothScroll(smoothScroller); } 

In this example, I use a helper method named "calculateCurrentDistanceToPosition". This can be a bit tricky, since it involves keeping track of your current scroll position, and calculating the scroll position of a given y position. You can find an example of how to keep track of the recycler's scroll y here.

Calculating the scroll y of a given position is really dependent on what your recycler is displaying. Assuming all your items are the same height, you can calculate this by performing the following calculation:

targetScrollY = targetPosition * itemHeight 

Then, to calculate the distance you need to scroll, simply subtract the current scroll y with the target scroll y:

private int calculateCurrentDistanceToPosition(int targetPosition) { int targetScrollY = targetPosition * itemHeight; return targetScrollY - currentScrollY; } 

2. Slowing down manual scrolling.

Once again, you need to edit your layout manager, this time - the scrollVerticallyBy method:

 @Override public int scrollVerticallyBy(int delta, Recycler recycler, State state) { // write your limiting logic here to prevent the delta from exceeding the limits of your list. int prevDelta = delta; if (getScrollState() == SCROLL_STATE_DRAGGING) delta = (int)(delta > 0 ? Math.max(delta * MANUAL_SCROLL_SLOW_RATIO, 1) : Math.min(delta * MANUAL_SCROLL_SLOW_RATIO, -1)); // MANUAL_SCROLL_SLOW_RATIO is between 0 (no manual scrolling) to 1 (normal speed) or more (faster speed). // write your scrolling logic code here whereby you move each view by the given delta if (getScrollState() == SCROLL_STATE_DRAGGING) delta = prevDelta; return delta; } 

Edit: In the above method, I call "getScrollState()". This is a method of RecyclerView. In this implementation, my custom LayoutManager is a nested class of my custom RecyclerView. If this doesn't work for you, you can try to grab the scroll state via some interface pattern.

3. Slow down the fling speed

Here you want to scale down the fling velocity. You will need to override the fling method inside your RecyclerView subclass:

@Override public boolean fling(int velocityX, int velocityY) { velocityY *= FLING_SCALE_DOWN_FACTOR; // (between 0 for no fling, and 1 for normal fling, or more for faster fling). return super.fling(velocityX, velocityY); } 

It's difficult for me to provide a more tailored solution, since you didn't post any of your code, or provide much information about your setup, but I hope this covers most bases and will help you find the best solution for you.

Sign up to request clarification or add additional context in comments.

15 Comments

What I want is to scroll down manual scrolling your second point. But methods and variables there are undefined. can you please update this.
I'm afraid that in order to help you any further, I'll need you to post more of your code so I can understand what you're doing and where you're stuck.
If instead of creating your own layout manager, your give the RecyclerView a new LinearLayoutManager, does the scrolling issue stop?
You copied my code sample, but didn't adapt it to your needs... "dy" needs to be refactored to "detla", MANUAL_SCROLL_SLOW_RATIO is a final static variable which you must define, and should be between 0 and 1, and of course, you need to implement your own logic for adjusting the positions of all the views, as well as detatching / scrapping unneeded views.
and calculateCurrentDistanceToPosition() ? where do you get this from?
|
36

I just simplifying Answer how to use it to control smooth scroll.

Create Class

import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; public class CustomRecyclerView extends RecyclerView { Context context; public CustomRecyclerView(Context context) { super(context); this.context = context; } public CustomRecyclerView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override public boolean fling(int velocityX, int velocityY) { velocityY *= 0.7; // velocityX *= 0.7; for Horizontal recycler view. comment velocityY line not require for Horizontal Mode. return super.fling(velocityX, velocityY); } } 

Adjust speed by Replacing 0.7 to your value.

Now use this class in your XML like this.

<<yourpackage>.CustomRecyclerView android:id="@+id/my_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical" /> 

Read RecyclerView in Java like.

CustomRecyclerView mRecyclerView; mRecyclerView = (CustomRecyclerView) findViewById(R.id.my_recycler_view); 

8 Comments

it does nothing for me
What you did ? as per I described in my answer
I did the same. But somehow setting velocityY to different values (even 0.1) does nothing
did you change in xml and java?
Excuse me, I am using horizontal mode and I just needed to use velocityX instead of velocityY. Now everything works excellent. Thank your for feedback +1
|
36

Simply implement smoothScrollToPosition() of your LinearLayoutManager:

LinearLayoutManager layoutManager = new LinearLayoutManager(this) { @Override public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) { LinearSmoothScroller smoothScroller = new LinearSmoothScroller(this) { private static final float SPEED = 300f;// Change this value (default=25f) @Override protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { return SPEED / displayMetrics.densityDpi; } }; smoothScroller.setTargetPosition(position); startSmoothScroll(smoothScroller); } }; 

4 Comments

you save a lot of time.
How do I make it smooth scroll to a position in 1 second, for example?
i get an error like "java.lang.IllegalStateException: If you provide an interpolator, you must set a positive duration". It needs duration.
@Blunderer, You're genius
0

use this for smooth scrolling

recyclerViewCart.isNestedScrollingEnabled = false 

1 Comment

I recommend that you add comments to your code as it will help other members to understand what you intended with this code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.