我有一个回收器视图,我想要平滑地向下滚动,然后以编程方式向上滚动到它,以向用户显示其中的完整内容。
我可以通过以下方式做到这一点:
final int height=recyclerView.getChildAt(0).getHeight();
recyclerView.smoothScrollToPosition(height);
recyclerView.postDelayed(new Runnable() {
public void run() {
recyclerView.smoothScrollToPosition(0);
}
},200);
但我想要的是减慢滚动速度,以便完整的内容清晰可见。
只是为了稍微改进一下答案:
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);
对于那些对重写 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);
我找到答案了!
您需要创建一个扩展
[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
,您就可以开始了。如果我有任何不清楚的地方,请告诉我。我很乐意提供帮助。
我制作了一个可以设置滚动速度变量的版本。
如果将
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);
}
}
基于@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)
}
要在给定时间内平滑滚动
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);
我是这样横向的
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)
//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 处理程序
class CustomLinearLayoutManager : LinearLayoutManager {
constructor(context: Context) : super(context) {}
constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout) {}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {}
companion object {
private val SMOOTHNESS_DISTANCE_IN_PIXELS = 500f
private val SMOOTHNESS_DURATION = 500f
}
override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State?, position: Int) {
val linearSmoothScroller = object : LinearSmoothScroller(recyclerView.context) {
override fun computeScrollVectorForPosition(targetPosition: Int): PointF? {
return this@CustomLinearLayoutManager
.computeScrollVectorForPosition(targetPosition)
}
override fun calculateTimeForScrolling(dx: Int): Int {
val proportion = dx.toFloat() / SMOOTHNESS_DISTANCE_IN_PIXELS
return (SMOOTHNESS_DURATION * proportion).toInt()
}
}
linearSmoothScroller.computeScrollVectorForPosition(position)
linearSmoothScroller.targetPosition = position
startSmoothScroll(linearSmoothScroller)
}
}