在嵌套的recyclerview中,scrollBy无法正常工作 [英] scrollBy doesn't work properly in nested recyclerview

查看:793
本文介绍了在嵌套的recyclerview中,scrollBy无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个垂直滚动的RecyclerView和水平滚动的内部RecyclerView,就像这样.

I have a vertically scrolling RecyclerView with horizontally scrolling inner RecyclerViews just like this.

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

With this implementation, users can scroll each horizontal recyclerview synchronously. However, when a user scroll vertically to the parent recyclerView, a new horizontal recyclerview which has just attached on window doesn't display on same scroll x position. This is normal. Because it has just created.

因此,我试图滚动到显示之前的滚动位置.就是这样:

So, I had tried to scroll to the scrolled position before it was displayed. Just like this:

注意:这位于父recyclerview的适配器中,其方向是垂直的.

Note: this is in adapter of the parent recyclerview whose orientation is vertical.

 @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);
        }
    }

如您所见,scrollBy不适用于第10行第11行第12 行和行13 之后,我调试了代码,以便能够找出正在发生的情况.当我使用scrollBy设置滚动位置时,childCount()对于第10行第11行第12行第13行因此它们不会滚动.但为什么 ?为什么其他人工作?

As you can see, scrollBy doesn't effect for row 10, row 11, row 12 and row 13 After that, I debugged the code to be able find out find out what's happening. When I set scroll position using scrollBy, childCount() return zero for row 10, row 11, row 12 and row 13 So they don't scroll. But why ? and Why others work ?

  • 我该如何解决?
  • 在onViewAttachedToWindow上滚动新附加的recyclervViews的位置正确吗?
  • How can I fix this ?
  • Is onViewAttachedToWindow right place to scroll new attached recyclervViews ?

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

Note: I have also test scrollToPosition(), it doesn't get any problem like this. But I can't use it at my case. Because users can scroll to the any x position which may not the exact position. So I need to set scroll position using x value instead of the position.

编辑:您可以检查源代码

推荐答案

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

I found a solution that is use scrollToPositionWithOffset method instead using scrollBy. Even if both of two scroll another position, they have really different work process in back side.

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

For example: if you try to use scrollBy to scroll any pixel position and your recyclerView had not been set any adapter which means there is no any data to display and so it has no any items yet, then scrollBy doesn't work. RecyclerView uses its layoutManager's scrollBy method. So in my case, I am using LinearLayoutManager to the horizontal recyclerViews.

让我们看看它在做什么:

Lets see what it's doing :

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会忽略滚动意图.

As you can see scrollBy ignores the scroll intentions if there is no any child at that time.

  if (getChildCount() == 0 || dy == 0) {
     return 0;
  }

另一方面,即使还没有任何设定数据,scrollToPosition也可以正常工作.

On the other hand scrollToPosition can work perfectly even if there is no any set data yet.

根据 Pro RecyclerView幻灯片,以下示例可完美运行.但是,使用scrollBy无法做到这一点.

According to the Pro RecyclerView slide, the below sample works perfectly. However you can not do that with scrollBy.

void onCreate(SavedInstanceState state) {
    ....
    mRecyclerView.scrollToPosition(selectedPosition);
    mRecyclerView.setAdapter(myAdapter);
}

结果,我对使用scrollToPositionWithOffset()所做的更改不多.

As a result, I have changed little thing to use scrollToPositionWithOffset().

在此实现之前,我正在计算确切的滚动x位置(以像素为单位).

Before this implementation I was calculating the exact scroll x position as a pixel.

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

After that, when the scroll came idle state, calculating the first complete visible position to the first parameter of the scrollToPositionWithOffset().

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

For second parameter which is the offset, I am getting the value using view.getLeft() function which helps to get left position of this view relative to its parent.

效果很好!

这篇关于在嵌套的recyclerview中,scrollBy无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆