Tia*_*ago 100 android scroll position smooth android-recyclerview
在RecyclerView上,我可以使用以下命令突然滚动到所选项目的顶部:
((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0);
Run Code Online (Sandbox Code Playgroud)
但是,这突然将项目移动到顶部位置.我想顺利地移动到项目的顶部.
我也尝试过:
recyclerView.smoothScrollToPosition(position);
Run Code Online (Sandbox Code Playgroud)
但它不能很好地工作,因为它不会将项目移动到选定的顶部位置.它只是滚动列表,直到位置上的项目可见.
Pau*_*hek 175
RecyclerView
被设计为可扩展的,因此不需要子类化LayoutManager
(如droidev建议)只是为了执行滚动.
相反,只需SmoothScroller
使用首选项创建一个SNAP_TO_START
:
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(context) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,您可以设置要滚动到的位置:
smoothScroller.setTargetPosition(position);
Run Code Online (Sandbox Code Playgroud)
并将SmoothScroller传递给LayoutManager:
layoutManager.startSmoothScroll(smoothScroller);
Run Code Online (Sandbox Code Playgroud)
dro*_*dev 109
为此,您必须创建自定义LayoutManager
public class LinearLayoutManagerWithSmoothScroller extends LinearLayoutManager {
public LinearLayoutManagerWithSmoothScroller(Context context) {
super(context, VERTICAL, false);
}
public LinearLayoutManagerWithSmoothScroller(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
RecyclerView.SmoothScroller smoothScroller = new TopSnappedSmoothScroller(recyclerView.getContext());
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
private class TopSnappedSmoothScroller extends LinearSmoothScroller {
public TopSnappedSmoothScroller(Context context) {
super(context);
}
@Override
public PointF computeScrollVectorForPosition(int targetPosition) {
return LinearLayoutManagerWithSmoothScroller.this
.computeScrollVectorForPosition(targetPosition);
}
@Override
protected int getVerticalSnapPreference() {
return SNAP_TO_START;
}
}
}
Run Code Online (Sandbox Code Playgroud)
将它用于RecyclerView并调用smoothScrollToPosition.
例如:
recyclerView.setLayoutManager(new LinearLayoutManagerWithSmoothScroller(context));
recyclerView.smoothScrollToPosition(position);
Run Code Online (Sandbox Code Playgroud)
这将滚动到指定位置的RecyclerView项目的顶部.
希望这可以帮助.
小智 10
我们可以这样尝试
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(), recyclerView.getAdapter().getItemCount());
Run Code Online (Sandbox Code Playgroud)
vov*_*ost 10
这是我在Kotlin中编写的扩展函数,可以直接在RecyclerView上调用(基于@Paul Woitaschek的回答):
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START) {
val smoothScroller = object: LinearSmoothScroller(this.context) {
override fun getVerticalSnapPreference(): Int {
return snapMode
}
override fun getHorizontalSnapPreference(): Int {
return snapMode
}
}
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
myRecyclerView.smoothSnapToPosition(itemPosition)
Run Code Online (Sandbox Code Playgroud)
我这样使用:
recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, new RecyclerView.State(), 5);
Run Code Online (Sandbox Code Playgroud)
我想更全面地解决滚动持续时间的问题,如果您选择任何早期的答案,滚动持续时间实际上会根据从当前位置到达目标位置所需的滚动量而发生巨大变化(并且令人无法接受)。
为了获得统一的滚动持续时间,速度(每毫秒像素数)必须考虑每个单独项目的大小 - 当项目具有非标准尺寸时,就会增加一个全新的复杂程度。
这可能就是为什么RecyclerView开发人员为平滑滚动这一重要方面部署了太硬的篮子的原因。
假设您想要半均匀的滚动持续时间,并且您的列表包含半均匀的项目,那么您将需要这样的东西。
/** Smoothly scroll to specified position allowing for interval specification. <br>
* Note crude deceleration towards end of scroll
* @param rv Your RecyclerView
* @param toPos Position to scroll to
* @param duration Approximate desired duration of scroll (ms)
* @throws IllegalArgumentException */
private static void smoothScroll(RecyclerView rv, int toPos, int duration) throws IllegalArgumentException {
int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000; // See androidx.recyclerview.widget.LinearSmoothScroller
int itemHeight = rv.getChildAt(0).getHeight(); // Height of first visible view! NB: ViewGroup method!
itemHeight = itemHeight + 33; // Example pixel Adjustment for decoration?
int fvPos = ((LinearLayoutManager)rv.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
int i = Math.abs((fvPos - toPos) * itemHeight);
if (i == 0) { i = (int) Math.abs(rv.getChildAt(0).getY()); }
final int totalPix = i; // Best guess: Total number of pixels to scroll
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(rv.getContext()) {
@Override protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_START;
}
@Override protected int calculateTimeForScrolling(int dx) {
int ms = (int) ( duration * dx / (float)totalPix );
// Now double the interval for the last fling.
if (dx < TARGET_SEEK_SCROLL_DISTANCE_PX ) { ms = ms*2; } // Crude deceleration!
//lg(format("For dx=%d we allot %dms", dx, ms));
return ms;
}
};
//lg(format("Total pixels from = %d to %d = %d [ itemHeight=%dpix ]", fvPos, toPos, totalPix, itemHeight));
smoothScroller.setTargetPosition(toPos);
rv.getLayoutManager().startSmoothScroll(smoothScroller);
}
Run Code Online (Sandbox Code Playgroud)
PS:我诅咒我开始不加选择地将ListView转换为RecyclerView 的那一天。
小智 6
覆盖LinearSmoothScroller中的calculateDyToMakeVisible/calculateDxToMakeVisible函数来实现偏移Y/X位置
override fun calculateDyToMakeVisible(view: View, snapPreference: Int): Int {
return super.calculateDyToMakeVisible(view, snapPreference) - ConvertUtils.dp2px(10f)
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
83593 次 |
最近记录: |