嵌套的RecyclerView中scrollBy方法无法正常工作

13

我有一个垂直滚动的RecyclerView,其中包含水平滚动的内部RecyclerViews,就像这样。

expl

使用这种实现方式,用户可以同步滚动每个水平RecyclerView。然而,当用户垂直滚动到父RecyclerView时,刚刚附加到窗口的新水平RecyclerView不会显示在相同的滚动x位置上。这是正常的,因为它刚刚被创建。
因此,我尝试在它显示之前滚动到滚动位置。就像这样:
注意:这是垂直方向的父RecyclerView的适配器。
 @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);
        }
    }

enter image description here

如您所见,scrollBy第10行第11行第12行第13行没有影响。之后,我调试了代码以找出问题所在。当我使用scrollBy设置滚动位置时,childCount()返回0,因此第10行第11行第12行第13行不会滚动。但是为什么?其他行为什么可以滚动?
  • 我该如何解决这个问题?
  • onViewAttachedToWindow是滚动新附加的可回收视图的正确位置吗?
注意:我还测试了scrollToPosition(),它没有遇到这样的问题。但是在我的情况下,我无法使用它。因为用户可以滚动到任何可能不是确切位置的x位置。因此,我需要使用x值而不是位置来设置滚动位置。

编辑:您可以查看源代码


你能否分享这段代码到Github或其他地方,以便于调试? - VinayagaSundar
我已经编辑了我的问题。您可以检查整个代码。 - ziLk
@Cheticamp 因为我两天前已经解决了这个问题 :) - ziLk
这解释了一切。如果您在此处发布答案,我会很感兴趣知道修复方法是什么。 - Cheticamp
@Cheticamp 你可以检查我的答案。 - ziLk
显示剩余4条评论
1个回答

6
我找到了一个解决方案,它使用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;
    }

正如您所看到的,如果此时没有任何子元素,scrollBy将忽略滚动意图。
  if (getChildCount() == 0 || dy == 0) {
     return 0;
  }

另一方面,即使没有设置任何数据,scrollToPosition 也可以完美地工作。根据Pro RecyclerView slide,下面的示例能够完美地运行。但是使用scrollBy则不行。
void onCreate(SavedInstanceState state) {
    ....
    mRecyclerView.scrollToPosition(selectedPosition);
    mRecyclerView.setAdapter(myAdapter);
}

作为结果,我已经改变了一些东西来使用scrollToPositionWithOffset()。在这个实现之前,我正在计算精确的滚动x位置作为像素。之后,当滚动处于空闲状态时,将第一个完整可见位置计算为scrollToPositionWithOffset()的第一个参数。对于第二个参数,即偏移量,我使用view.getLeft()函数获取值,该函数有助于获取此视图相对于其父视图的左侧位置。

enter image description here

它完美地运行了!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接