How can I control the scrolling speed of recyclerView.smoothScrollToPosition(position)?
I have a recycler view, and I want a smooth scrolldown and then scrollup to it programatically to show the complete content in it to user.
I can do this by:
final int height=recyclerView.getChildAt(0).getHeight();
recyclerView.smoothScrollToPosition(height);
recyclerView.postDelayed(new Runnable() {
public void run() {
recyclerView.smoothScrollToPosition(0);
}
},200);
But what I want is to slow down the scrolling speed, so that the complete content gets visible clearly.
Just to improve on the answer a little:
public class SpeedyLinearLayoutManager extends LinearLayoutManager {
private static final float MILLISECONDS_PER_INCH = 5f; //default is 25f (bigger = slower)
public SpeedyLinearLayoutManager(Context context) {
super(context);
}
public SpeedyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public SpeedyLinearLayoutManager(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()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return super.computeScrollVectorForPosition(targetPosition);
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
}
And then set SpeedyLayoutManager to your RecyclerView:
recyclerView.setLayoutManager(new SpeedyLinearLayoutManager(context, SpeedyLinearLayoutManager.VERTICAL, false);
For those uninterested in overriding LinearLayoutManager (or whichever subclass you're using), you can just call startSmoothScroll(smoothScroller)
directly on the layout manager.
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
layoutManager.startSmoothScroll(linearSmoothScroller);
I found an answer!
You need to make a custom class extending [LinearLayoutManager][1]
and then override the [smoothScrollToPosition][1]
method. Inside, you need to create a new [LinearSmoothScroller][1]
and override its calculateSpeedPerPixel method Then use that LinearSmoothScroller
to complete the scroll.
Here is my example :
public class CustomLinearLayoutManager extends LinearLayoutManager{
@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 = 100f;
@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);
}
}
Assign this CustomLinearLayoutManager
to your RecyclerView
and you should be good to go. Let me know if I was unclear in anything. I'll be happy to help.
I've made a version that you can set the scrolling speed variable.
If you set factor
to 2, it will be twice as slow as default.
public class VariableScrollSpeedLinearLayoutManager extends LinearLayoutManager {
private final float factor;
public VariableScrollSpeedLinearLayoutManager(Context context, float factor) {
super(context);
this.factor = factor;
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
final LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return VariableScrollSpeedLinearLayoutManager.this.computeScrollVectorForPosition(targetPosition);
}
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return super.calculateSpeedPerPixel(displayMetrics) * factor;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
}