Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding items to Endless Scroll RecyclerView with a ReverseLayout recyclerview

In a normal recyclerview, the newest items are all at the top and if you add an item into the recyclerview, it pushes the existing items down and the new item takes the top position.

In a reverseLayout recyclerview, the newest items are all at the bottom and if you add an item into the recyclerview, it is added right at the bottom. This kind of layout is quite useful for things like comment feeds where you expect the latest comments to be at the bottom.

A good example of this is the Facebook comment feed when you comment on a friend's status for example. You can see that the comments all have the time that they were posted at the bottom and the times are decreasing from 12 hours to 10 hours from top to bottom:

facebook comment feed

The reverseLayout is quite easy to set and I have done it using this code:

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

I'm however struggling to attach a reverse endless scroll listener. I'm using the following Vilen's code from my question a while back (Adding items to Endless Scroll RecyclerView with ProgressBar at bottom) and modifying it so that it the onLoadMoreListener will only activate itself when it is scrolling up instead of down. You want to scroll up to older comments:

    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
        final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        //if you add on addOnScrollListener, it will cause the scroll listener to be called twice each time you reset your adapter
        recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            int firstVisibleItem;
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                final int currentFirstVisibleItem = linearLayoutManager.findFirstVisibleItemPosition();
                totalItemCount = linearLayoutManager.getItemCount();
                lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();

                if(lastVisibleItem > firstVisibleItem)
                {
                    Log.i("SCROLLING UP","TRUE");
                    if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
                        current_page++;
                        if (onLoadMoreListener != null) {
                            onLoadMoreListener.onLoadMore(current_page);
                        }
                        loading = true;
                    }
                }
                lastVisibleItem=firstVisibleItem;
            }
        });
    }

When the onLoadMoreListener is called, the following code is called in my activity class:

    CommentsAdapter.OnLoadMoreListener onLoadMoreListener = new CommentsAdapter.OnLoadMoreListener() {
    @Override
    public void onLoadMore(int current_page) {
        //get the firstCommentId on the list of comments so that we can send it to the server to fetch comments less than that comment id to display in our recyclerview
        firstCommentId = comments.get(0).getId();
        //add empty item for progress bar / wheel and display the progress bar / wheel
        Comment comment = new Comment();
        comment.setViewType(Constants.COMMENT_PROGRESS_BAR);
        comments.add(0, comment);
        mCommentAdapter.notifyItemInserted(0);
        mCommentAdapter.notifyItemRangeChanged(1, comments.size());

        //CODE FOR NETWORK OPERATIONS GOES HERE TO FETCH THE NEXT FEW COMMENTS WHEN SCROLLING UP//
    }
};

However, the onLoadMoreListener doesn't seem to be called at all when I scroll up.

I also made sure I had at least 10 comments in my feed and 5 was loaded before and 5 more should be loaded when I scroll up.

Does anything know what I'm doing wrong with this reverse OnLoadMoreListener?

EDIT:

The reverseLayout recyclerview actually does work with the original code from Vilen, I have uploaded a github repo to show this:

https://github.com/Winghin2517/ReverseLayoutRecyclerview

There is still an issue with when the onLoadMoreListener is activated though - If the comment list only comprises of 3 comments and there is no more comments to add on, I don't want the onLoadMoreListener to activate at all when I initially view my comments - when I first click on my app to see the comments. Right now, when I click to view my comments, even though there are 3 comments in the Dataset, the progressBar is still displayed and the disappears after a 2 seconds which I think is not necessary (see github repo where I demonstrate this).

Disabling it when there is only 3 comments is also not a good idea as the onLoadMoreListener acts as like a swipeToRefresh object. If there are more comments from the user subsequent to when he views the comment feed, he can swipe down and the onLoadMoreListener will display those comments.

Is there a way to just disable it when the feed loads initially?

like image 954
Simon Avatar asked Dec 18 '15 11:12

Simon


People also ask

How do I stop refreshing RecyclerView data scroll to top position android?

Make a setDataList method in your adapter class. And set your updated list to adapter list. And then every time of calling API set that list to setDataList and call adapter. notifyDataSetChanged() method of your adapter class.

Does RecyclerView scroll?

To be able to scroll through a vertical list of items that is longer than the screen, you need to add a vertical scrollbar. Inside RecyclerView , add an android:scrollbars attribute set to vertical .

Does RecyclerView automatically scroll?

Does RecyclerView automatically scroll? There is a method in RecyclerView which is smoothScrollToPosition() which take position of recyclerview to scroll that position to current position.


1 Answers

Simon: solution I previously proposed here works fine with reverse layout without any modification. The only thing I'd add for reverse layout is to scroll automatically to first item when you show it first time but that's up to you. Now getting back to issue you have. You mentioned that when you scroll nothing happens. so my guess is that you initialize your recylcer view in a wrong order. Make sure you do it like this

mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);

mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter<>(myDataset, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);

Note that layout manager gets instantiated first, then you set it and after that you provide adapter. Let me know if that was the case.

Edit Just bringing up this from comment below:

forget about what we have with onLoadMoreListener and all scrolling stuff just use standard RecyclerView wrapped in SwipeToRefreshLayout

like image 103
Vilen Avatar answered Oct 19 '22 19:10

Vilen