1

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;
}

}

  • If you consider at some point to try using [Cloud Firestore](https://firebase.google.com/docs/firestore/), here you can find a tutorial on how to create a complete and functional [Firestore Chat App](https://www.youtube.com/playlist?list=PLn2n4GESV0Ak1HiH0tTPTJXsOEy-5v9qb). It also contains the the feature that you are looking for. – Alex Mamo Feb 06 '19 at 10:31
  • For sooth scroll to top you have to tried this -> https://stackoverflow.com/questions/32159724/scroll-to-top-in-recyclerview-with-linearlayoutmanager – Nilesh Panchal Feb 06 '19 at 11:12
  • I did try smooth scroll to top but it didn't work. For some reason my IDE is not recognizing mChatLayoutManager.scrollToPositionWithOffset(0, 0). Thanks for the suggestions! – Asif Bin Zahir Feb 06 '19 at 17:15
  • Hello @AsifBinZahir use Collections.reverse(abc); instead of Collections.sort it will work 100% try it. – Nilesh Panchal Feb 07 '19 at 05:14

1 Answers1

0

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

Nilesh Panchal
  • 1,059
  • 1
  • 10
  • 24