如何控制 recyclerView.smoothScrollToPosition(position) 的滚动速度?
How can I control the scrolling speed of recyclerView.smoothScrollToPosition(position)?
我有一个回收站视图,我想要一个平滑的向下滚动然后以编程方式向上滚动到它以向用户显示其中的完整内容。
我可以通过以下方式做到这一点:
final int height=recyclerView.getChildAt(0).getHeight();
recyclerView.smoothScrollToPosition(height);
recyclerView.postDelayed(new Runnable() {
public void run() {
recyclerView.smoothScrollToPosition(0);
}
},200);
但是我想要的是放慢滚动速度,让完整的内容清晰可见。
我找到答案了!
您需要自定义 class 扩展 [LinearLayoutManager][1]
,然后覆盖 [smoothScrollToPosition][1]
方法。在内部,您需要创建一个新的 [LinearSmoothScroller][1]
并覆盖其 calculateSpeedPerPixel 方法,然后使用该 LinearSmoothScroller
来完成滚动。
这是我的例子:
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);
}
}
将此 CustomLinearLayoutManager
分配给您的 RecyclerView
,您就可以开始了。让我知道我是否有任何不清楚的地方。我很乐意提供帮助。
稍微改进一下答案:
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);
}
}
然后将 SpeedyLayoutManager 设置为您的 RecyclerView:
recyclerView.setLayoutManager(new SpeedyLinearLayoutManager(context, SpeedyLinearLayoutManager.VERTICAL, false);
我做了一个可以设置滚动速度变量的版本。
如果将 factor
设置为 2,它将比默认值慢两倍。
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);
}
}
对于那些对覆盖 LinearLayoutManager(或您正在使用的任何子类)不感兴趣的人,您可以直接在布局管理器上调用 startSmoothScroll(smoothScroller)
。
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
layoutManager.startSmoothScroll(linearSmoothScroller);
我是这样横过来的
private val milliSecondsPerInch = 500f
var horizontalLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
创建
horizontalLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recycler_banner?.layoutManager = horizontalLayoutManager
然后
val linearSmoothScroller: LinearSmoothScroller =
object : LinearSmoothScroller(this) {
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
return milliSecondsPerInch / displayMetrics.densityDpi
}
}
linearSmoothScroller.targetPosition = 3 //the last position of the item in the list
horizontalLayoutManager.startSmoothScroll(linearSmoothScroller)
在给定时间内平滑滚动 RecyclerView
您可以覆盖 LinearSmoothScroller#calculateSpeedPerPixel
,如下例所示。
final Context context = getContext();
final RecyclerView recyclerView = new RecyclerView(context);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);
final YourCustomAdapter adapter = new YourCustomAdapter();
recyclerView.setAdapter(new YourCustomAdapter());
final float scrollDuration = 30000f; // in milliseconds
final LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return scrollDuration / recyclerView.computeVerticalScrollRange();
}
};
linearSmoothScroller.setTargetPosition(adapter.getItemCount() - 1);
layoutManager.startSmoothScroll(linearSmoothScroller);
基于@Bartek Mrozinski 的回答。这是我的 Kotlin 扩展函数,用于在给定时间内平滑滚动 RecyclerView。
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
val scrollDuration = 500f;
val smoothScroller = object : LinearSmoothScroller(this.context) {
override fun getVerticalSnapPreference(): Int = snapMode
override fun getHorizontalSnapPreference(): Int = snapMode
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics?): Float {
return scrollDuration / computeVerticalScrollRange();
}
}
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
}
//i am using the handler..
//where cretedactivtyadapter is my adpater classs
// instiate your adpter class like this
private CreatedActivityAdapter createdActivityAdapter;
//call autoscroll in your oncreate//
public void autoscroll()
{ ////auto scroll is used for the recycler view to scroll it self
final int speedScroll = 1;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
int count = 0;
@Override
public void run()
{
if (count == createdActivityAdapter.getItemCount())
count=0;
if (count < createdActivityAdapter.getItemCount()){
recyclerView.smoothScrollToPosition(++count);
handler.postDelayed(this,speedScroll);
}
}
};
handler.postDelayed(runnable,speedScroll);
}
//并在创建时调用 theis 处理程序
我有一个回收站视图,我想要一个平滑的向下滚动然后以编程方式向上滚动到它以向用户显示其中的完整内容。
我可以通过以下方式做到这一点:
final int height=recyclerView.getChildAt(0).getHeight();
recyclerView.smoothScrollToPosition(height);
recyclerView.postDelayed(new Runnable() {
public void run() {
recyclerView.smoothScrollToPosition(0);
}
},200);
但是我想要的是放慢滚动速度,让完整的内容清晰可见。
我找到答案了!
您需要自定义 class 扩展 [LinearLayoutManager][1]
,然后覆盖 [smoothScrollToPosition][1]
方法。在内部,您需要创建一个新的 [LinearSmoothScroller][1]
并覆盖其 calculateSpeedPerPixel 方法,然后使用该 LinearSmoothScroller
来完成滚动。
这是我的例子:
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);
}
}
将此 CustomLinearLayoutManager
分配给您的 RecyclerView
,您就可以开始了。让我知道我是否有任何不清楚的地方。我很乐意提供帮助。
稍微改进一下答案:
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);
}
}
然后将 SpeedyLayoutManager 设置为您的 RecyclerView:
recyclerView.setLayoutManager(new SpeedyLinearLayoutManager(context, SpeedyLinearLayoutManager.VERTICAL, false);
我做了一个可以设置滚动速度变量的版本。
如果将 factor
设置为 2,它将比默认值慢两倍。
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);
}
}
对于那些对覆盖 LinearLayoutManager(或您正在使用的任何子类)不感兴趣的人,您可以直接在布局管理器上调用 startSmoothScroll(smoothScroller)
。
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
layoutManager.startSmoothScroll(linearSmoothScroller);
我是这样横过来的
private val milliSecondsPerInch = 500f
var horizontalLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
创建
horizontalLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
recycler_banner?.layoutManager = horizontalLayoutManager
然后
val linearSmoothScroller: LinearSmoothScroller =
object : LinearSmoothScroller(this) {
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
return milliSecondsPerInch / displayMetrics.densityDpi
}
}
linearSmoothScroller.targetPosition = 3 //the last position of the item in the list
horizontalLayoutManager.startSmoothScroll(linearSmoothScroller)
在给定时间内平滑滚动 RecyclerView
您可以覆盖 LinearSmoothScroller#calculateSpeedPerPixel
,如下例所示。
final Context context = getContext();
final RecyclerView recyclerView = new RecyclerView(context);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(layoutManager);
final YourCustomAdapter adapter = new YourCustomAdapter();
recyclerView.setAdapter(new YourCustomAdapter());
final float scrollDuration = 30000f; // in milliseconds
final LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
@Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return scrollDuration / recyclerView.computeVerticalScrollRange();
}
};
linearSmoothScroller.setTargetPosition(adapter.getItemCount() - 1);
layoutManager.startSmoothScroll(linearSmoothScroller);
基于@Bartek Mrozinski 的回答。这是我的 Kotlin 扩展函数,用于在给定时间内平滑滚动 RecyclerView。
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
val scrollDuration = 500f;
val smoothScroller = object : LinearSmoothScroller(this.context) {
override fun getVerticalSnapPreference(): Int = snapMode
override fun getHorizontalSnapPreference(): Int = snapMode
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics?): Float {
return scrollDuration / computeVerticalScrollRange();
}
}
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
}
//i am using the handler..
//where cretedactivtyadapter is my adpater classs
// instiate your adpter class like this
private CreatedActivityAdapter createdActivityAdapter;
//call autoscroll in your oncreate//
public void autoscroll()
{ ////auto scroll is used for the recycler view to scroll it self
final int speedScroll = 1;
final Handler handler = new Handler();
final Runnable runnable = new Runnable() {
int count = 0;
@Override
public void run()
{
if (count == createdActivityAdapter.getItemCount())
count=0;
if (count < createdActivityAdapter.getItemCount()){
recyclerView.smoothScrollToPosition(++count);
handler.postDelayed(this,speedScroll);
}
}
};
handler.postDelayed(runnable,speedScroll);
}
//并在创建时调用 theis 处理程序