Yasin Kaçmaz Yasin Kaçmaz - 2 months ago 16
Android Question

Android Recyclerview load more on scrolltop

Hey community I want to make a

RecyclerView
like in the chat applications.

I tried
setStackFromEnd
and it's working good.

final LinearLayoutManager llm = new LinearLayoutManager(getApplicationContext());
llm.setOrientation(LinearLayoutManager.VERTICAL);
llm.setStackFromEnd(true);


My on load more code based on this tutorial, At the end of tutorial you should see a video : Recyclerview Bottom Progress

mRecyclerView.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();

if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});


So I need to make a
RecyclerView
like in chat applications. Stack from end is working perfect but I need to trigger load more method when I go top instead of going bottom. Also add new items on top instead of bottom. Thanks in advance.

Answer

You don't need to make use of onScrollListener, if you simply want to show a Button "Load Earlier Messages" at the top. You can simply create an xml for your load more Button, make that as the first row of your RecyclerView and create an Interface to handle click events. I am posting code for the Adpater from one of my projects. Hope that will help you in getting some idea to proceed further.

/**
 * Created by Mukesh on 21/12/2015.
 */
public class ChatListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context mContext;
    private List<UserMessage> userMessagesList;
    private LayoutInflater mLayoutInflater;
    private static final int ROW_TYPE_LOAD_EARLIER_MESSAGES = 0;
    private static final int ROW_TYPE_SENDER = 1;
    private static final int ROW_TYPE_RECEIVER = 2;
    private int userId;
    private boolean isLoadEarlierMsgs;
    private LoadEarlierMessages mLoadEarlierMessages;

    public ChatListAdapter(Context context, int userId, List<UserMessage> userMessagesList) {
        mContext = context;
        this.userMessagesList = userMessagesList;
        mLayoutInflater = LayoutInflater.from(mContext);
        this.userId = userId;
        mLoadEarlierMessages = (LoadEarlierMessages) mContext;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {
            case ROW_TYPE_LOAD_EARLIER_MESSAGES:
                return new LoadEarlierMsgsViewHolder(mLayoutInflater.inflate(R.layout
                        .row_load_earlier_messages, parent, false));
            case ROW_TYPE_SENDER:
                return new SenderMsgViewHolder(mLayoutInflater.inflate(R.layout.row_sender_msg,
                        parent, false));
            case ROW_TYPE_RECEIVER:
                return new ReceiverMsgViewHolder(mLayoutInflater.inflate(R.layout
                        .row_receiver_msg, parent, false));
            default:
                return null;
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
            case ROW_TYPE_LOAD_EARLIER_MESSAGES:
                LoadEarlierMsgsViewHolder loadEarlierMsgsViewHolder =
                        (LoadEarlierMsgsViewHolder) holder;
                if (isLoadEarlierMsgs) {
                    loadEarlierMsgsViewHolder.btLoadEarlierMessages
                            .setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    if (mLoadEarlierMessages != null) {
                                        mLoadEarlierMessages.onLoadEarlierMessages();
                                    }
                                }
                            });
                } else {
                    loadEarlierMsgsViewHolder.btLoadEarlierMessages.setVisibility(View.GONE);
                }
                break;
            case ROW_TYPE_SENDER:
                SenderMsgViewHolder senderMsgViewHolder = (SenderMsgViewHolder) holder;
                // set data for your sender chat bubble
                break;
            case ROW_TYPE_RECEIVER:
                ReceiverMsgViewHolder receiverMsgViewHolder = (ReceiverMsgViewHolder) holder;
                // set data for your receiver chat bubble
                break;
        }
    }

    @Override
    public int getItemCount() {
        return userMessagesList.size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return ROW_TYPE_LOAD_EARLIER_MESSAGES; // row load earlier messages
        } else if (userMessagesList.get(position - 1).getUser_id() == userId) {
            return ROW_TYPE_SENDER; // sender row;
        } else {
            return ROW_TYPE_RECEIVER; // receiver row;
        }
    }

    public interface LoadEarlierMessages {
        void onLoadEarlierMessages();
    }


    public void setLoadEarlierMsgs(boolean isLoadEarlierMsgs) {
        this.isLoadEarlierMsgs = isLoadEarlierMsgs;
    }

    static class LoadEarlierMsgsViewHolder extends RecyclerView.ViewHolder {

        @Bind(R.id.btLoadEarlierMsgs) Button btLoadEarlierMessages;

        public LoadEarlierMsgsViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    static class SenderMsgViewHolder extends RecyclerView.ViewHolder {

        public SenderMsgViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }

    static class ReceiverMsgViewHolder extends RecyclerView.ViewHolder {

        public ReceiverMsgViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }
    }
}

And finally implement the LoadEarlierMessages listener in your ChatActivity and Override the onLoadEarlierMessages() method

    /**
     * Created by Mukesh on 21/12/2015.
     */
    public class ChatActivity extends AppCompatActivity
            implements ChatListAdapter.LoadEarlierMessages {

       // getting users recent messages and init RecyclerView
       private void showUserMessages() {
        // initialising LayoutManager for RecyclerView and setting that to RecyclerView
        mLinearLayoutManager = new LinearLayoutManager(this);
        mLinearLayoutManager.setStackFromEnd(true); // to start the list from bottom
        rvChatsList.setLayoutManager(mLinearLayoutManager);

        // initialising RecyclerView Adapter and setting that to the RecyclerView
        mChatListAdapter = new ChatListAdapter(this, userId, userMessagesList);
        rvChatsList.setAdapter(mChatListAdapter);

        // getting count of friend/contact messages and toggling visibility of load more button accordingly
        int count = mDataBaseHandler.getCountOfMessages(contactId);
        if (count != 0) {
            if (count > Constants.MESSAGES_LIMIT_FOR_LOCAL_DATABASE) {
                mChatListAdapter.setLoadEarlierMsgs(true);
            } else {
                mChatListAdapter.setLoadEarlierMsgs(false);
            }
            userMessagesList.addAll(mDataBaseHandler.getAllMessagesOfContact(contactId));
            mChatListAdapter.notifyDataSetChanged();
        }

    }

        @Override
        public void onLoadEarlierMessages() {
            ArrayList<UserMessage> tempList = mDataBaseHandler
                    .getPreviousMessagesOfContact(contactId, userMessagesList.size());
            if (tempList.size() > 0) {
                if (tempList.size() < Constants.MESSAGES_LIMIT_FOR_LOCAL_DATABASE) {
                    mChatListAdapter.setLoadEarlierMsgs(false);
                }
                View v = rvChatsList.getChildAt(0);
                int top = (v == null) ? 0 : v.getTop();
                for (int i = 0; i < tempList.size(); i++) {
                    userMessagesList.add(0, tempList.get(i));
                }
                mChatListAdapter.notifyDataSetChanged();
                mLinearLayoutManager.scrollToPositionWithOffset(tempList.size(), top);
            } else {
                mChatListAdapter.setLoadEarlierMsgs(false);
            }
        }

    }

Hope this will help..!!