Search code examples
androidandroid-fragmentsfirebase-realtime-databaseandroid-recyclerviewgridlayoutmanager

How to display most recent chat message in Recycler View?


I am very new to Android/Java development. I am working on a project that involves a chat activity.

I want the activity to automatically scroll to the bottom of the chat screen (most recent chat message).

I tried displaying the getItem count using Toast - I was able to verify that I can pick up the int position of my Recyclerview items correctly. However, I am struggling to use ScrollToPosition or SmoothScroltoPosition to get my desired outcome.

Any ideas as to how I can automatically scroll to my most recent chat item?

Here is my Chat activity below:

public class ChatActivity extends AppCompatActivity {

private RecyclerView mRecyclerView;
private RecyclerView.Adapter mChatAdapter;
private RecyclerView.LayoutManager mChatLayoutManager;
private  String currentUserID, matchId, chatId;

private EditText mSendEditText;
private Button mSend;

DatabaseReference mDatabaseChat;
DatabaseReference mDatabaseChatDB;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_chat);

    matchId = getIntent().getExtras().getString("matchid");
    currentUserID = FirebaseAuth.getInstance().getCurrentUser().getUid();

    mDatabaseChat = FirebaseDatabase.getInstance().getReference().child("User").child(currentUserID).child("connections").child("matches").child(matchId).child("ChatId");
    mDatabaseChatDB = FirebaseDatabase.getInstance().getReference().child("Chat");

    getChatID();

    mSend = (Button) findViewById(R.id.send);
    mSendEditText = (EditText) findViewById(R.id.message);


    mSend.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            sendMessage();
        }

        private void sendMessage() {
            String sendMessageText = mSendEditText.getText().toString();
            if (!sendMessageText.isEmpty()){
                DatabaseReference newMessageDb = mDatabaseChatDB.push();

                Map newMessage = new HashMap<>();
                newMessage.put("createdByUser",currentUserID);
                newMessage.put("text", sendMessageText);

                newMessageDb.setValue(newMessage);
            }
            mSendEditText.setText(null);
        }
    });

    mRecyclerView = (RecyclerView) findViewById(R.id.chatview);
    mRecyclerView.setNestedScrollingEnabled(false);
    mRecyclerView.setHasFixedSize(false);
    mChatLayoutManager = new LinearLayoutManager(ChatActivity.this);
    mRecyclerView.setLayoutManager(mChatLayoutManager);
    mChatAdapter = new ChatAdapter(getDataSetChat(),ChatActivity.this);
    mRecyclerView.setAdapter(mChatAdapter);

}

private void getChatID(){
    mDatabaseChat.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                chatId = dataSnapshot.getValue().toString();
                mDatabaseChatDB = mDatabaseChatDB.child(chatId);
                getChatMessages();
            }
        }

        private void getChatMessages() {
            mDatabaseChatDB.addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                    if (dataSnapshot.exists()){
                        String message = null;
                        String currentuser = null;

                        if (dataSnapshot.child("text").getValue() != null ){
                            message = dataSnapshot.child("text").getValue().toString();
                        }

                        if (dataSnapshot.child("createdByUser").getValue() != null ){
                            currentuser = dataSnapshot.child("createdByUser").getValue().toString();
                        }
                        if(message!= null && currentuser !=null){
                            Boolean currentUserBoolean = false;
                            if(currentuser.equals(currentUserID)){
                                currentUserBoolean = true;
                            }
                            ChatObject newMessage = new ChatObject(message,currentUserBoolean);
                            resultsChat.add(newMessage);
                            mChatAdapter.notifyDataSetChanged();
                        }
                    }
                }

                @Override
                public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

                }

                @Override
                public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {

        }
    });
}
private ArrayList<ChatObject> resultsChat = new ArrayList<ChatObject>();
private List<ChatObject> getDataSetChat() {
    return resultsChat;
}

}


Solution

  • Hello @Asif Bin Zahit for getting the recent message on top you have to make some changes in code like following

    After adding latest message in array list resultsChat.add(newMessage) You have to sort the array list in descending order and then after calling the notifyDataSetChanged

    If you have already records in the list before setting the adapter then you have to Sort list as described below and after that set adapter to recycler view

    Collections.sort(getDataSetChat())
    mChatAdapter = new ChatAdapter(getDataSetChat(),ChatActivity.this);
    mRecyclerView.setAdapter(mChatAdapter);
    

    When adding a new message to the list

    resultsChat.add(newMessage);
    Collections.sort(resultsChat);
    mChatAdapter.notifyDataSetChanged();
    

    It will always add your latest message on top of the list in recyclerview