嵌套在RecyclerView中的NestedScrollView向下滚动时未触发OnScrollListener。

6

编辑:

我从Web服务加载了200多条数据。当我向下滚动RecyclerView时,它没有触发scrollListener。

因为,如果我不使用dy>0的条件,它会在最初进入此活动时加载所有下一个20个数据,20个数据等等。

以下是相关代码:

日志记录:

E/dy: 0

活动代码:

recyclerView = (RecyclerView) findViewById(R.id.rv_list_tab_home_recycler);

recyclerView.setHasFixedSize(true);

mLayoutManager = new LinearLayoutManager(this);

recyclerView.setLayoutManager(mLayoutManager);

//homePostitemsAdapter = new UserPostAdapter(TabHomeActivity.this, homePostItemsList);
homePostitemsAdapter = new TabHomeAdapter(homePostItemsList, recyclerView);

//  recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(homePostitemsAdapter);
recyclerView.setNestedScrollingEnabled(false);

适配器代码:

private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;

public TabHomeAdapter(List<HomePostItems> objects, RecyclerView recycle) {

    homePostArrListItems = objects;

    if (recycle.getLayoutManager() instanceof LinearLayoutManager) {

        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recycle
                .getLayoutManager();

        Log.e("LinearLayoutManager", "Test");

        recycle.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView,
                                           int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager
                                .findLastVisibleItemPosition();
                Log.e("dy", ""+dy);

                if (!loading
                                && totalItemCount <= (lastVisibleItem + visibleThreshold ) && dy > 0) {
                    // End has been reached
                    // Do something

                    Log.e("totalItemCount", ""+totalItemCount);
                    Log.e("lastVisibleItem", ""+lastVisibleItem);
                    Log.e("visibleThreshold", ""+visibleThreshold);
                    Log.e("loading", ""+loading);
                    Log.e("onLoadMoreListener", ""+onLoadMoreListener);

                    if (onLoadMoreListener != null) {;
                        onLoadMoreListener.onLoadMore();
                    }

                    loading = true;
                }

            }
        });
    } 

    public void setLoaded() {
        loading = false;
    }

    @Override
    public int getItemCount() {    
        return homePostArrListItems.size(); 
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }

    public static class ProgressViewHolder extends RecyclerView.ViewHolder {
        public ProgressBar progressBar;
        public ProgressViewHolder(View v) {
            super(v);
            progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
        }
    }
}

一开始我参与这个活动时,dy的值是0。当我滚动RecyclerView时,在LogCat中没有触发dy。

我认为这是因为有NestedScrollView的原因,它会导致它不起作用。但我需要嵌套滚动视图,因为我需要在RecyclerView之前滚动一些视图。


这篇回答可能会有用:https://dev59.com/-1oT5IYBdhLWcg3wxxzg - crgarridos
@cgarrido,感谢你给我指出那个链接。现在我明白了,因为嵌套的滚动视图导致它不能触发滚动监听器。但是我需要嵌套滚动视图来修复垂直RecyclerView中的水平RecyclerView。 - Stephen
我不确定,但是如果你需要设置recyclerView.setNestedScrollingEnabled(true); 那么它可以解决你的问题。如果有父级RecyclerView,则不知道这段代码... - crgarridos
如果我设置NestedScrollingEnabled(true),它会减慢滚动速度(影响性能速度)。 - Stephen
@Abbas的回答没有解决你的问题吗? - crgarridos
@cgarrido,那个也不起作用。 - Stephen
4个回答

6
如果您想要懒加载,则可以查看我的RecyclerAdapter
@Override
public void onBindViewHolder(VH viewHolder, final int position) {

    // Set Data to Views

    if(position == count) {
        // When last item is reached.

        if (onLoadMoreListener != null) {;
            onLoadMoreListener.onLoadMore();
        }
    }
}

我认为这是一种更简单且相当廉价的方式来实现“懒加载”。


你能帮我解决类似的问题吗?http://stackoverflow.com/questions/41930139/staggered-gridview-recycleview-with-load-more-functionality - Ravindra Kushwaha

6
尝试这个,它对我有效...
nestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener) (v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
        if(v.getChildAt(v.getChildCount() - 1) != null) {
            if ((scrollY >= (v.getChildAt(v.getChildCount() - 1).getMeasuredHeight() - v.getMeasuredHeight())) &&
                    scrollY > oldScrollY) {
                    //code to fetch more data for endless scrolling
            }
        }
    });

Reference : NestedScrollView


我尝试了同样的代码,但遇到了一个问题,即使我只滚动一次,这个条件也会变为true两次。我在其中调用了分页API,因此API被调用了两次。有什么解决办法吗? - krupa parekh

3

试试这个,对我有用 #在RecycleView中使用NestedScrollView实现分页

 public abstract class NestedScroll implements NestedScrollView.OnScrollChangeListener {

    public void onScrollChange(NestedScrollView view, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

        if (view.getChildAt(view.getChildCount() - 1) != null) {
            if ((scrollY >= (view.getChildAt(view.getChildCount() - 1).getMeasuredHeight() - view.getMeasuredHeight())) &&
                    scrollY > oldScrollY) {
                onScroll();
            }

        }
    }

    public abstract void onScroll();
}

and call ->

//NestedScrollView nested
nested.setOnScrollChangeListener(new NestedScroll() {
        @Override
        public void onScroll() {
            //do here 
        }
    });

请解释一下你的代码@Shiv Kumar,因为我想在recyclerview的倒数第三个项目可见时调用API。目前这是不可能的,因为LinearLayoutManager在findLastVisibleItemPosition上没有给出正确的位置。 - Raghav Satyadev
1
这是你的解决方案@RaghavSatyadev..只需将其放在onScrolled内部int totalcount = linearLayoutManager.findFirstVisibleItemPosition() + linearLayoutManager.getChildCount(); if (!data) { if ((linearLayoutManager.getItemCount() - totalcount) == 3) { data = true; Log.d("data", "new data"); //在此处调用您的方法 data = false; } - Shiv Kumar

1
将RecycleView视图更改为以下内容。
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setHasFixedSize(true);
recyclerView.setNestedScrollingEnabled(false);

2. 将滚动监听器设置到您的NestedScroll上,像这样

  NestedScrollView nestedScrollView = NestedScrollView)findViewById(R.id.nestedscroll);
         nestesdScroll.getViewTreeObserver().addOnScrollChangedListener(new 
         ViewTreeObserver.OnScrollChangedListener() {
                    @Override
                    public void onScrollChanged() {
                        View view = (View) nestesdScroll.getChildAt(nestesdScroll.getChildCount() - 1);
                        int diff = (view.getBottom() - (nestesdScroll.getHeight() + nestesdScroll.getScrollY()));
                        if (diff == 0) {  
                           //code to fetch more data for endless scrolling                
                           load_more_data();
                        }
                    }
                });

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