1

I am trying to implement infinte scroll but I can't make it to work as I can see by the logs that I've placed that the onScrolled method is only called once when the page first loads and not after, even if I scroll all the way to the bottom. I try going up and down many times but it is never called again.

Could it have anything to do with it being inside a swipeRefreshLayout?

This is my code

Initiating variables

lateinit var lastVisible: DocumentSnapshot
var isScrolling = false
var isLastItemReached = false

Grabbing data from the server function

fun listenToQuestions() {

    questionsRowLayoutAdapter.clear()
    questionsBlockLayoutAdapter.clear()



    db.collection("questions").whereEqualTo("language", currentLanguage)
        .orderBy("last_interaction", Query.Direction.DESCENDING).limit(10)
        .get().addOnSuccessListener {

            for (document in it) {
                val questionObject = document.toObject(Question::class.java)

                           questionsAdapter.add(
                                (SingleBoardBlock(
                                    questionObject,
                                    activity as MainActivity
                                ))
                            )

            }
            Toast.makeText(this.context, "first batch", Toast.LENGTH_SHORT).show()

            questionsAdapter.notifyDataSetChanged()

            lastVisible = it.documents[it.size() - 1]

            val onScrollListener = object : RecyclerView.OnScrollListener() {
                override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                    super.onScrollStateChanged(recyclerView, newState)
                    if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                        isScrolling = true
                        Toast.makeText(activity, "scrolling", Toast.LENGTH_SHORT).show()
                        Log.d("itemsvaues", "new state statement true")
                    } else {
                        Log.d("itemsvaues", "new state statement false")
                    }
                }

                override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                    super.onScrolled(recyclerView, dx, dy)

                    val thisLayoutManager = recyclerView.layoutManager as LinearLayoutManager

                    val firstVisibleItem = thisLayoutManager.findFirstVisibleItemPosition()
                    val visibleItemCount = thisLayoutManager.childCount
                    val totalItemCount = thisLayoutManager.itemCount

                    val countCheck = firstVisibleItem + visibleItemCount == totalItemCount
                    Log.d("itemsvaues", "$firstVisibleItem $visibleItemCount $totalItemCount $countCheck")
                    Log.d("itemsvaues", "is scrolling $isScrolling")
                    Log.d("itemsvaues", "last item reached $isLastItemReached")


                    if (isScrolling && countCheck && !isLastItemReached) {
                        isScrolling = false
                        Log.d("itemsvaues", "if happened")

                        db.collection("questions").whereEqualTo("language", currentLanguage)
                            .orderBy("last_interaction", Query.Direction.DESCENDING).startAfter(lastVisible)
                            .limit(10).get()
                            .addOnSuccessListener { querySnapshot ->

                                for (document in querySnapshot) {
                                    val questionObject = document.toObject(Question::class.java)

                           questionsAdapter.add(
                                (SingleBoardBlock(
                                    questionObject,
                                    activity as MainActivity
                                ))
                            )

                                    }
                                }
                                Toast.makeText(activity, "next batch", Toast.LENGTH_SHORT).show()

                                questionsAdapter.notifyDataSetChanged()

                                lastVisible = querySnapshot.documents[querySnapshot.size() - 1]
                                Log.d("itemsvaues", "next query happened")

                                if (querySnapshot.size() < 10) {
                                    isLastItemReached = true
                                    Toast.makeText(activity, "reached last", Toast.LENGTH_SHORT).show()
                                    Log.d("itemsvaues", "last item reached")

                                }
                            }
                    } else {
                        Log.d("itemsvaues", "if didn't happen")
                    }
                }
            }
            questionsRecycler.addOnScrollListener(onScrollListener)
        }
}

And these are the logs:

2019-07-20 12:48:49.149 29888-29888/io.poolclub D/itemsvaues: 0 10 10 true
2019-07-20 12:48:49.149 29888-29888/io.poolclub D/itemsvaues: is scrolling false
2019-07-20 12:48:49.149 29888-29888/io.poolclub D/itemsvaues: last item reached false
2019-07-20 12:48:49.149 29888-29888/io.poolclub D/itemsvaues: if didn't happen
2019-07-20 12:48:52.181 29888-29888/io.poolclub D/itemsvaues: new state statement true
2019-07-20 12:48:52.328 29888-29888/io.poolclub D/itemsvaues: new state statement false
2019-07-20 12:48:52.530 29888-29888/io.poolclub D/itemsvaues: new state statement false
2019-07-20 12:48:53.481 29888-29888/io.poolclub D/itemsvaues: new state statement true
2019-07-20 12:48:53.645 29888-29888/io.poolclub D/itemsvaues: new state statement false
Tsabary
  • 1,688
  • 1
  • 9
  • 30

2 Answers2

0

Probably not useful to the original poster anymore, but to other people that come across the same issue:

In my case the problem was that I forgot I have put the RecyclerView inside a NestedScrollView and set it to android:nestedScrollingEnabled="false", which indeed makes the listener fire only once. You can either add the listener to the NestedScrollView then, or see if some of the options discussed in the question below can help you: Recyclerview onscrolllistener not working when setNestedScrollingEnabled to false

Of course there can be other reasons, but this is one of the most easily came across ones.

NoHarmDan
  • 333
  • 3
  • 13
-1

you can try this code

listview.addOnScrollListener(new RecyclerView.OnScrollListener() {

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


                visibleItemCount = manager.getChildCount();
                totalItemCount = manager.getItemCount();
                pastVisiblesItems = manager.findFirstVisibleItemPosition();

                if (dy > 0 && pastVisiblesItems >= totalItemCount && !isLoading) {
                    isLoading = true;
                    LoadMoreData();
                }

            }

        });

With this code, you can scroll to the end of the list and load the new information If you need information from item 10 to the end of the list to be loaded

change

if (dy > 0 && pastVisiblesItems >= totalItemCount && !isLoading) {
   isLoading = true;
   LoadMoreData();
}

to

if (dy > 0 && pastVisiblesItems >= totalItemCount - 10 && !isLoading) {
   isLoading = true;
   LoadMoreData();
}
  • My problem is not the code as I've copied it from a tutorial and it seems to be a good code, my problem is that `onScrolled` isn't called when it should. So changing to this code wouldn't change much because `onScrolled` would still not be called – Tsabary Jul 20 '19 at 23:52
  • This answer indeed does not answer the question at all. – NoHarmDan Jan 29 '21 at 15:16