scrollBy在嵌套的recyclerview中无法正常工作

ziL*_*iLk 11 android scroll android-recyclerview

我有一个垂直滚动RecyclerView与水平滚动内部RecyclerViews就像这样.

EXPL

通过此实现,用户可以同步滚动每个水平回收站视图.但是,当用户垂直滚动到父级recyclelerView时,刚刚附加在窗口上的新水平回收视图不会显示在同一滚动x位置上.这个是正常的.因为它刚刚创建.

所以,我曾试图在显示之前滚动到滚动位置.像这样:

注意:这是在父回收者视图的适配器中,其方向是垂直的.

 @Override
    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        CellColumnViewHolder viewHolder = (CellColumnViewHolder) holder;
        if (m_nXPosition != 0) {
             // this doesn't work properly 
             viewHolder.m_jRecyclerView.scrollBy(m_nXPosition, 0);
        }
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

正如您所看到的,scrollBy第10行,第11行,第12行第13 没有影响.之后,我调试了代码,以便找出发生了什么.当我使用scrollBy设置滚动位置时,childCount()为第10 ,第11 ,第12 第13 返回零,因此它们不会滚动.但为什么 ?为什么其他人工作?

  • 我怎样才能解决这个问题 ?
  • 是onViewAttachedToWindow正确的位置滚动新附加的recyclervViews?

注意:我也测试过scrollToPosition(),它没有遇到这样的问题.但我不能在我的情况下使用它.因为用户可以滚动到可能不是确切位置的任何x位置.所以我需要使用x值而不是位置来设置滚动位置.

编辑:您可以查看源代码

ziL*_*iLk 5

我找到了一个使用scrollToPositionWithOffset方法而不是使用的解决方案scrollBy。即使两者都滚动另一个位置,它们在背面的工作过程确实不同。

例如:如果您尝试使用scrollBy滚动任何像素位置并且您的 recyclerView 尚未设置任何适配器,这意味着没有任何数据可显示,因此它还没有任何项目,则scrollBy不起作用。RecyclerView 使用其 layoutManager 的scrollBy方法。所以就我而言,我正在使用LinearLayoutManager水平 recyclerViews。

让我们看看它在做什么:

int scrollBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
        if (getChildCount() == 0 || dy == 0) {
            return 0;
        }
        mLayoutState.mRecycle = true;
        ensureLayoutState();
        final int layoutDirection = dy > 0 ? LayoutState.LAYOUT_END : LayoutState.LAYOUT_START;
        final int absDy = Math.abs(dy);
        updateLayoutState(layoutDirection, absDy, true, state);
        final int consumed = mLayoutState.mScrollingOffset
                + fill(recycler, mLayoutState, state, false);
        if (consumed < 0) {
            if (DEBUG) {
                Log.d(TAG, "Don't have any more elements to scroll");
            }
            return 0;
        }
        final int scrolled = absDy > consumed ? layoutDirection * consumed : dy;
        mOrientationHelper.offsetChildren(-scrolled);
        if (DEBUG) {
            Log.d(TAG, "scroll req: " + dy + " scrolled: " + scrolled);
        }
        mLayoutState.mLastScrollDelta = scrolled;
        return scrolled;
    }
Run Code Online (Sandbox Code Playgroud)

如您所见scrollBy,如果当时没有任何孩子,则忽略滚动意图。

  if (getChildCount() == 0 || dy == 0) {
     return 0;
  }
Run Code Online (Sandbox Code Playgroud)

另一方面,scrollToPosition即使没有任何设置数据也可以完美运行。

根据Pro RecyclerView 幻灯片,以下示例完美运行。但是,您不能使用 scrollBy 做到这一点。

void onCreate(SavedInstanceState state) {
    ....
    mRecyclerView.scrollToPosition(selectedPosition);
    mRecyclerView.setAdapter(myAdapter);
}
Run Code Online (Sandbox Code Playgroud)

结果,我改变了一些小东西来使用scrollToPositionWithOffset()

在此实现之前,我正在计算作为像素的确切滚动 x 位置。

之后,当滚动进入空闲状态时,计算第一个完整的可见位置到scrollToPositionWithOffset().

对于作为偏移量的第二个参数,我使用view.getLeft()函数获取值,该函数有助于获取此视图相对于其父视图的左侧位置。

在此处输入图片说明

而且效果很好!!