(Smooth)ScrollToPosition 不能与 RecyclerView 一起正常工作
Posted
技术标签:
【中文标题】(Smooth)ScrollToPosition 不能与 RecyclerView 一起正常工作【英文标题】:(Smooth)ScrollToPosition doesn't work properly with RecyclerView 【发布时间】:2015-08-30 23:34:52 【问题描述】:我正在使用带有 GridLayoutManager 的基本 RecyclerView。我观察到 smoothScrollToPosition 和 scrollToPosition 都不能正常工作。
a) 在使用smoothScrollToPosition
时,我经常收到来自RecyclerView
的错误
“RecyclerView﹕在平滑滚动时越过了目标位置。”
并且RecyclerView
未正确滚动(通常会错过目标行)。这主要是在我尝试滚动到某行的第一项时观察到的
b) 使用scrollToPosition
时,它似乎工作得很好,但大多数时候我只能看到该行的第一项,其余的不显示。
您能否给我一些提示,如何使至少其中一种方法正常工作?
非常感谢!
【问题讨论】:
如果你有一个负数位置(例如,你想到达空适配器中的最后一个位置),你会得到一个错误:***.com/questions/57937265/…。 【参考方案1】:我终于可以让它工作了! LinearLayoutManager.scrollToPositionWithOffset(int, int)
成功了。
【讨论】:
我遇到了类似的问题,该方法也为我解决了问题......但我实际上正在尝试实现smoothScroll。你也是吗? 使用gridLayoutManager.scrollToPositionWithOffset(index, 0)
也为我工作。
是的,LayoutManager.scrollToPosition()
可能效果不佳,但 LinearLayoutManager.scrollToPositionWithOffset()
很好:D 这很神奇。
典型用法是:LinearLayoutManager llm = (LinearLayoutManager) recyclerView.getLayoutManager(); llm.scrollToPositionWithOffset(10, 0);
但请注意,您不再获得smoothScrollToPosition()
拥有的平滑滚动动画。
不工作!与 mRecyclerView.scrollToPosition(position) 相同【参考方案2】:
我也有同样的问题,但通过自定义 SmoothScroller 设法解决了这个问题
让自定义 LayoutManager 如下
public class CustomLayoutManager extends LinearLayoutManager
private static final float MILLISECONDS_PER_INCH = 50f;
private Context mContext;
public CustomLayoutManager(Context context)
super(context);
mContext = context;
@Override
public void smoothScrollToPosition(RecyclerView recyclerView,
RecyclerView.State state, final int position)
LinearSmoothScroller smoothScroller =
new LinearSmoothScroller(mContext)
//This controls the direction in which smoothScroll looks
//for your view
@Override
public PointF computeScrollVectorForPosition
(int targetPosition)
return CustomLayoutManager.this
.computeScrollVectorForPosition(targetPosition);
//This returns the milliseconds it takes to
//scroll one pixel.
@Override
protected float calculateSpeedPerPixel
(DisplayMetrics displayMetrics)
return MILLISECONDS_PER_INCH/displayMetrics.densityDpi;
;
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
(上面给出的代码里面注释的文档)请设置上面的LayoutManager 到recyerview
CustomLayoutManagerlayoutManager = new CustomLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.smoothScrollToPosition(position);
通过使用自定义布局管理器
滚动到位置 在我的情况下你也可以使用
recyclerView.scrollToPosition(position)
如果你想调整smoothScrollToPosition的速度,请覆盖
private static final float MILLISECONDS_PER_INCH = 50f;
在自定义布局管理器中。 因此,如果我们将值设置为 1f,smoothScrollToPosition 会像 scrollToPosition 一样快。增加值会延迟,减少会加快滚动速度。 希望这会有用。
【讨论】:
scrollToPositionWithOffset 有效,但为了平滑滚动,我需要 Ramz 的回答。【参考方案3】:就我而言,
mRecyclerView.scrollToPosition(10);
也没有工作。 但是
mRecyclerView.smoothScrollToPosition(10);
对我来说很好......
【讨论】:
【参考方案4】:单击 EditText 从 RecyclerView 中的任何位置平滑向下滚动到底部。
edittext.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
rv_commentList.postDelayed(new Runnable()
@Override
public void run()
rv_commentList.scrollToPosition(rv_commentList.getAdapter().getItemCount() - 1);
, 1000);
);
【讨论】:
【参考方案5】:上述任何解决方案可能不起作用的另一个原因是,如果您的 RecyclerView 嵌入在 NestedScrollView 中。在这种情况下,您必须在 NestedScrollView 上调用滚动操作。
例如:
nestedScrollview.smoothScrollTo(0,0)
【讨论】:
拯救了这一天! 谢谢!没有想到这一点,有一段时间遇到了麻烦。【参考方案6】:recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView,new RecyclerView.State(),currentPosition);
【讨论】:
recyclerView。 smoothScrollToPosition(position) 调用您在评论中描述的方法。你能解释一下你为什么要设置新的状态吗? recyclerView 已经有状态了?【参考方案7】:尝试测量项目的宽度或高度并调用 smoothScrollBy(int dx, int dy)。
【讨论】:
【参考方案8】:设备旋转后如何平滑滚动并保存RecyclerView
垂直位置:
这是适用于我的情况的方法,
public class MainFragment extends Fragment //OR activity it's //fragment in my case
....
@Override
public void onLoadFinished(@NonNull Loader<List<Report>> loader, List<Report> objects) // or other method of your choice, in my case it's a Loader
RecyclerView recyclerViewRv = findViewById(........;
.....
recyclerViewRv.setAdapter(.....Your adapter);
recyclerViewRv.addOnScrollListener(new RecyclerView.OnScrollListener()
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState)
super.onScrollStateChanged(recyclerView, newState);
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
recyclerScrollY = recyclerViewRv. computeVerticalScrollOffset();
);
//Apply smooth vertical scroll
recyclerViewRv.smoothScrollBy(0,recyclerScrollY);
//Save vertical scroll position before rotating devices
@Override
public void onSaveInstanceState(@NonNull Bundle outState)
super.onSaveInstanceState(outState);
outState.putInt("recyclerScrollY",recyclerScrollY);
//BackUp vertical scroll position after rotating devices
@Override
public void onCreate(@Nullable Bundle savedInstanceState)
super.onCreate(savedInstanceState);
if(savedInstanceState != null)
recyclerScrollY = savedInstanceState.getInt("recyclerScrollY");
//If you want to perform the same operation for horizontal scrolling just add a variable called recyclerScrollX = recyclerScrollY = recyclerViewRv. computeHorizontalScrollOffset(); then save in bundle
【讨论】:
【参考方案9】:我遇到了一个奇怪的问题,其中 smoothScrollToPosition
只是偶尔工作。
将 smoothScrollToPosition 放入 Handler Post 之后 延迟 1 秒延迟,效果很好。
参考以下 Kotlin 示例:
Handler().postDelayed(
recyclerViewObject.smoothScrollToPosition(0) // mention the position in place of 0
, 1000) // 1000 indicates the 1 second delay.
【讨论】:
【参考方案10】:这个扩展非常有用,请尝试。
fun RecyclerView.smoothSnapToPosition(position: Int, snapMode: Int = LinearSmoothScroller.SNAP_TO_START)
val smoothScroller = object : LinearSmoothScroller(this.context)
override fun getVerticalSnapPreference(): Int = snapMode
override fun getHorizontalSnapPreference(): Int = snapMode
smoothScroller.targetPosition = position
layoutManager?.startSmoothScroll(smoothScroller)
【讨论】:
【参考方案11】:调用recyclerView smoothScroll 无效,因为recyclerView 本身不处理它的布局。
你应该做的是调用布局管理器滚动方法。
这应该看起来像这样
mRecyclerView.getLayoutManager().scrollToPosition(desiredPosition);
【讨论】:
我试过了,但问题仍然存在。应该可以,但不知何故。 RecyclerView 将滚动调用路由到其 LayoutManager 因此这不会改变任何事情,除非引入潜在的 NPE。【参考方案12】:如果您想快速滚动到 RecyclerView 顶部的某个位置,只需使用 LinearLayoutManager.scrollToPositionWithOffset 与 0 作为偏移量。
例子:
mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.scrollToPositionWithOffset(myPosition, 0);
smoothScrollToPosition 非常慢。如果您想快速获得一些东西,请使用 scrollToPositionWithOffset。
【讨论】:
【参考方案13】:当您使用 scrollToPosition 时,它将显示在回收站视图的顶部。
但是如果你使用 smoothScrollToPosition 它将滚动直到它进入 Window Visible。这就是为什么当 smoothScool 到下面的项目时,它会在底部显示它
【讨论】:
【参考方案14】:实际上,如果你在一个 NestedScrollView 中有一个 RecyclerView,那么每次你想去 RecyclerView 的开头时都必须使用这两行:
nestedScrollView.smoothScrollTo(0, 0);
layoutManager.scrollToPositionWithOffset(0, 0);
这完全适合我。
【讨论】:
【参考方案15】:这对我有用
Handler().postDelayed(
(recyclerView.getLayoutManager() as LinearLayoutManager).scrollToPositionWithOffset( 0, 0)
, 100)
【讨论】:
【参考方案16】:所以我一直在寻找一种解决方案,以在另一个布局中使用 recyclerview 回到顶部,该布局在其顶部有一个视图(在我的情况下,我有一个带有 TextView 和我的 recyclerview 的 LinearLayout)。因此,平滑滚动只会走到第一项的一半。
这是我所做的,效果非常好(Kotlin 解决方案):
back_to_top.setOnClickListener
GlobalScope.launch(Dispatchers.Main)
GlobalScope.launch(Dispatchers.Main)
recyclerview.layoutManager?.smoothScrollToPosition(recyclerview, RecyclerView.State(), 0)
delay((recyclerview.layoutManager as LinearLayoutManager).findLastVisibleItemPosition() * 100L)
.join()
recyclerview.scrollToPosition(0)
back_to_top.visibility = View.GONE
我在这里所做的是平滑滚动到第一个元素并将滚动延迟 100 毫秒乘以最后一个可见项目,然后调用 scrollToPosition(0)(正确地转到顶部)
【讨论】:
【参考方案17】:这些答案都不适合我。我需要smoothScrollToPosition
,但@Ramz 的回答没有用。我发现它会一直过度滚动,但只会在一个方向上滚动。我发现这似乎是物品装饰师把它扔掉了。我有一个水平布局,我想在每个项目之后添加一个空格,除了最后一个,它不喜欢这种不对称。只要我在每个项目后面加上一个空格,它就起作用了!
【讨论】:
以上是关于(Smooth)ScrollToPosition 不能与 RecyclerView 一起正常工作的主要内容,如果未能解决你的问题,请参考以下文章
scrollToPosition(),使用片段更新RecyclerView时
Android Leanback 库 HorizontalGridView scrollToPosition 不起作用
R语言使用pROC包绘制ROC曲线并使用smooth函数绘制平滑的ROC曲线(方法包括:binormaldensityfitdistrlogcondenslogcondens.smooth)