RecyclerView.OnScrollListener:一次滚动实例被多次调用 [英] RecyclerView.OnScrollListener: being called multiple times for once instance of scroll

查看:846
本文介绍了RecyclerView.OnScrollListener:一次滚动实例被多次调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有水平布局的recyclerview,一次只能看到一个视图:

I have a recyclerview with horizontal layout and only one view is visible at a time:

mRecyclerView = findViewById(R.id.rvmain);
mRecyclerView.setOnFlingListener(null);
final SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRecyclerView);
mLayoutManager = new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MainActivityRVAdapter(postsModels,MainActivity.this);
mRecyclerView.setAdapter(mAdapter);

使用onScrolllistener,每次我滚动时都想知道开始位置和结束位置.我正在使用以下代码:

using onScrolllistener, everytime I scroll I want to know the starting position and end position. I am using the below code:

    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);


        if(count == 0) {
            View centerView = snapHelper.findSnapView(mLayoutManager);
            if(centerView != null){
                initial_position = mLayoutManager.getPosition(centerView);
                //initial_position2 = ((LinearLayoutManager)mRecyclerView.getLayoutManager()).findFirstVisibleItemPosition();
                Log.e("Initial Item Position:",""+initial_position);
                //Log.e("Initial Item Position2:",""+initial_position2);
            }
            count ++;
        }



        // get newstate position
        if(newState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
            View centerView = snapHelper.findSnapView(mLayoutManager);
            if(centerView != null){
                int pos = mLayoutManager.getPosition(centerView);

                count = 0; // in idle state clear the count again
                Log.e("Snapped Item Position:",""+pos);
            }
        }


    }

我得到的结果是:

E/Initial Item Position:: 0
E/Snapped Item Position:: 1
E/Initial Item Position:: 1
E/Snapped Item Position:: 1
E/Initial Item Position:: 1
E/Snapped Item Position:: 1
E/Initial Item Position:: 1
E/Snapped Item Position:: 1

它多次返回位置.我想检查最终职位和初始职位之间的区别. 我只想要开始和结束,这样我就可以进行比较和检查:

And it returns positions multiple times. I wanted to check the difference between final and initial positions. I wanted only the start and end so that i can compare and check i.e:

E/Initial Item Position:: 0 and

E/Snapped Item Position:: 1

推荐答案

我遇到了同样的问题.而我发现: RecyclerView.OnScrollListener调用 onScrolled(...) SCROLL_STATE_DRAGGING 中多次>或 SCROLL_STATE_SETTLING .

I've met the same problem. And what i found: RecyclerView.OnScrollListener calls onScrolled(...) multiple times while in SCROLL_STATE_DRAGGING or SCROLL_STATE_SETTLING.

我开始收听第二次回调:
onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState)
在最终状态下我们很有趣 SCROLL_STATE_IDLE

I started listen to a second calback:
onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState)
We are interesting in a final state SCROLL_STATE_IDLE.

因此,在这种情况下,我们必须覆盖onScrollStateChanged(...),检查并忽略除SCROLL_STATE_IDLE之外的所有状态,并在空闲时获得最终位置.

So in this case we have to override onScrollStateChanged(...), check and ignore all states except SCROLL_STATE_IDLE and get final position while idle.

但如文档中所述a>,onScrolled(...)

如果布局后可见项范围发生变化,也会调用

计算.在这种情况下,dx和dy将为0.

will also be called if visible item range changes after a layout calculation. In that case, dx and dy will be 0.

在实践中,我发现如果我们调用adapter.notifyDataSetChanged()并且可见位置是" 0 "(即首次启动),则不会调用onScrollStateChanged(...),而会调用onScrolled(...)一次是 dx == dy == 0 .

On practice i found that if we call adapter.notifyDataSetChanged() and visible position is "0" (ie. on first start), onScrollStateChanged(...) will not be called and onScrolled(...) will be called once with dx == dy == 0.

最终的变体如下:

private int recyclerVisiblePosition;    
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
   super.onScrollStateChanged(recyclerView, newState);

   if (newState != RecyclerView.SCROLL_STATE_IDLE) {
      return;
   }

   getNewPosition(recyclerView);
}

@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);

    if (dx == 0 && dy == 0) {
        getNewPosition(recyclerView);
    } 
}

private void getNewPosition(@NonNull final RecyclerView recyclerView) {
    final LinearLayoutManager layoutManager = ((LinearLayoutManager)recyclerView.getLayoutManager());
    if (layoutManager != null) {
        recyclerVisiblePosition = layoutManager.findLastVisibleItemPosition();
    }
}

这篇关于RecyclerView.OnScrollListener:一次滚动实例被多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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