Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView onScrolled method of addOnScrollListener not called except only once

Background:

I am implementing pagination logic with RecyclerView by adding addOnScrollListener function.

Problem faced:

The onScrolled method is called once when the RecyclerView adapter is loaded with dy value of 0. However when the list reaches its end when scrolled, the onScrolled method is not triggered while the onScrollStateChanged is triggered correctly.

Here is my Adapter:

HistoryAdapter(Context context, ArrayList<HistoryItem> items, RecyclerView recyclerView) {
        inflater = LayoutInflater.from(context);
        this.items = items;
        preferences = PreferenceManager.getDefaultSharedPreferences(context);
        this.context = context;
        this.recyclerView = recyclerView;

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

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                Timber.w("onScrolled.. %s", dy);

                if (dy > 0) {
                    totalItemCount = linearLayoutManager.getItemCount();
                    lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
                    Timber.e("totalItemCount: %s", totalItemCount);
                    Timber.e("lastVisibleItem: %s", lastVisibleItem);

                    if (!isLoading && totalItemCount <= (lastVisibleItem + 1)) {

                        Timber.i("End reached...");
                        if (onLoadMoreListener != null) {
                            //Log.i(TAG, "Episodes Adapter: onLoadMore calling...");
                            onLoadMoreListener.onLoadMore();
                        }
                        isLoading = true;
                    }
                }
            }

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

            }
        });
    }

Recycler:

private void setupRecycler() {
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(linearLayoutManager);
        historyAdapter = new HistoryAdapter(getActivity(), historyItems, recyclerView);
        recyclerView.setAdapter(historyAdapter);
        historyAdapter.setClickListener(this);
        historyAdapter.setOnLoadMoreListener(this);
        historyAdapter.setErrorClickListener(this);
    }

My Recycler xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/medium_text_color_blue"
        android:padding="12dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="start"
            android:text="#"
            android:textColor="@android:color/white"
            android:textStyle="bold" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="4.5"
            android:gravity="start"
            android:text="CLASS"
            android:textAllCaps="true"
            android:textColor="@android:color/white"
            android:textStyle="bold" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center"
            android:text="Date"
            android:textAllCaps="true"
            android:textColor="@android:color/white"
            android:textStyle="bold" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center"
            android:text="time"
            android:textAllCaps="true"
            android:textColor="@android:color/white"
            android:textStyle="bold" />
    </LinearLayout>

    <FrameLayout
        android:layout_below="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/no_reflection_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:layout_gravity="center"
            android:text="No Reflection History found!" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/history_recycler"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </FrameLayout>
</RelativeLayout>

What I have researched:

There are many such issues already posted at StackOverflow but most of them point to a solution that is to remove the parent ScrollView of the RecyclerView which is stopping the onScrolled method to be triggered, however this seems to be not an issue I am facing.

RecyclerView.onScrolled() not getting called

RecyclerView onScrolled not called when use scrollToPosition

RecyclerView onScrolled not being fired at all

RecyclerView not calling onScrolled at the bottom

android RecyclerView onScrolled not call

https://github.com/passsy/ArrayAdapter/issues/4

like image 639
itabdullah Avatar asked Jan 11 '20 12:01

itabdullah


1 Answers

An alternative is to check if the recycler can scroll vertically if it cannot then it means it has reached the bottom.

Try this

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)

                if (!recyclerView.canScrollVertically(1)) {
                    // Load more
                }
            }
}

`
like image 84
christoandrew Avatar answered Nov 07 '22 11:11

christoandrew