平滑滚动不适用于 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 上调用,如果recyclerViewAdapter 太忙而无法生成视图项,那么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

Xamarin Forms:捏缩放和滚动不适用于 WebView 内容

Android 平滑滚动到底部

Android WebView 平滑滚动