平滑滚动不适用于 Android RecyclerView 的初始滚动
Posted
技术标签:
【中文标题】平滑滚动不适用于 Android RecyclerView 的初始滚动【英文标题】:Smooth Scroll Not Working on Initial Scroll for Android RecyclerView 【发布时间】:2017-04-23 05:53:42 【问题描述】:我正在开发一款 android 应用,该应用只能在一台运行 KitKat 的设备上运行。
我在其他物理平板电脑和 genymotion 上使用的 RecylerView 的平滑滚动功能不幸停止在它需要使用的一台设备上工作。
它不是滚动到某个位置,而是越过目标位置并一直滚动到底部,看起来真的很糟糕。
我能够追踪到 RecyclerView 类中抽象 SmoothScroller 的错误。
if (getChildPosition(mTargetView) == mTargetPosition)
onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction);
mRecyclingAction.runIfNecessary(recyclerView);
stop();
else
Log.e(TAG, "Passed over target position while smooth scrolling.");
mTargetView = null;
我使用的是我在网上找到的 SnappingLinearLayoutManager,但将它换成了 Android 的普通 LinearLayoutManager,仍然遇到同样的问题。
列表有 7 个项目(用户一次可以看到 4 个),我滚动到第 5 个项目(位置 4)项目。
当我滚动到第三个时,我没有收到此错误。
此外,在我上下滚动列表一次后,错误停止发生。
编辑: 我可以使用 layoutManager.scrollToPositionWithOffset();但我正在尝试使用平滑的滚动动画来做到这一点。
这是我的一些代码和详细信息:
private void setupMainRecyclerViewWithAdapter()
mainLayoutManager = new SnappingLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mainListRecyclerView.setLayoutManager(mainLayoutManager);
settingsMainListAdapter = new SettingsListAdapter(SettingsActivity.this,
settingsPresenter.getSettingsItems(),
settingsPresenter);
mainListRecyclerView.setAdapter(settingsMainListAdapter);
mainListRecyclerView.addItemDecoration(new BottomOffsetDecoration(EXTRA_VERTICAL_SCROLLING_SPACE));
@Override
public void scrollMainList(boolean listAtTop)
if(listAtTop)
mainListRecyclerView.smoothScrollToPosition(4);
moveMainMoreButtonAboveList();
else
mainListRecyclerView.smoothScrollToPosition(0);
moveMainMoreButtonBelowList();
【问题讨论】:
尝试改用layoutManager.scrollToPosition(index);
对不起,我可以使用 layoutManager.scrollToPositionWithOffset();但我试图用平滑的滚动动画来做到这一点。很好的捕捉@BNK。我会将该编辑添加到我的问题中。
也许他们可以帮助mcochin.wordpress.com/2015/05/13/…和blog.stylingandroid.com/scrolling-recycler-view-part-2
是的,我尝试实施 mcochin 博客文章中的解决方案,但遇到了相同的“平滑滚动时越过了目标位置”。错误。我会调查另一个。感谢您的帮助!
【参考方案1】:
如果您调用recyclerView.smoothScrollToPosition(pos)
将立即在UI thread
上调用,如果recyclerView
的Adapter
太忙而无法生成视图项,那么smoothScrollToPosition
的调用将被错过,因为@987654326 @ 有没有数据来平滑滚动。所以最好在recyclerView.post()
的后台线程中执行此操作。通过调用它,它会进入Main thread
队列,并在其他挂起的任务完成后执行。
因此,您应该做一些适合我的情况的事情:
recyclerView.post(new Runnable()
@Override
public void run()
recyclerView.smoothScrollToPosition(pos);
);
【讨论】:
【参考方案2】:好吧,我意识到为时已晚,但我尝试了一些不同的解决方案并找到了一个......
在自定义 LinearSmoothScroller 中,我覆盖 updateActionForInterimTarget
@Override
protected void updateActionForInterimTarget(Action action)
action.jumpTo(position);
与scrollToPositionWithOffset相比,它看起来不是很流畅,但不是即时的。
【讨论】:
【参考方案3】:只需添加一行即可平滑滚动
recyclerView.setNestedScrollingEnabled(false);
它会正常工作
【讨论】:
为我工作,但谁能解释为什么会这样? 这仅适用于带有嵌套滚动区域的回收站视图【参考方案4】:看看hasPendingAdapterUpdates()。您可以将其与协程的 delay() 或 Thread.sleep() 一起使用,以使支持数据在滚动之前可用。
【讨论】:
以上是关于平滑滚动不适用于 Android RecyclerView 的初始滚动的主要内容,如果未能解决你的问题,请参考以下文章
jQuery 平滑滚动在 iPad 和 iPhone 上不起作用
RecyclerView - 如何平滑滚动到嵌套滚动视图内某个位置的项目顶部?
iScroll - 保留原生垂直滚动 - 适用于 iOS,不适用于 Android