Reputation: 1460
The issue is that the recyclerview scrolls down almost a complete row when the soft keyboard appears or disappears.
Here is a visual example:
The layout for the activity uses a MessageInput and MessageList object from the ChatKit UI library and is as follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="apps.cal.calchat.ChatActivity.ChatView">
<TextView
android:id="@+id/chatIsTypingTextView"
android:layout_width="match_parent"
android:layout_marginLeft="8dp"
android:layout_height="wrap_content"
android:layout_above="@+id/chatMessageInput"/>
<com.stfalcon.chatkit.messages.MessageInput
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:id="@+id/chatMessageInput"
android:layout_width="0dp"
android:layout_height="wrap_content" />
<com.stfalcon.chatkit.messages.MessagesList
android:id="@+id/chatMessagesList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="@+id/chatIsTypingTextView"
/>
</RelativeLayout>
The activity also has adjustPan set in the manifest:
<activity
android:name=".ChatActivity.ChatView"
android:windowSoftInputMode="adjustPan|stateHidden"/>
The Recyclerviews linear layout manager is set as vertical, with a reverse layout and with the default item animator:
public <MESSAGE extends IMessage>
void setAdapter(MessagesListAdapter<MESSAGE> adapter, boolean reverseLayout) {
SimpleItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setSupportsChangeAnimations(false);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(),
LinearLayoutManager.VERTICAL, reverseLayout);
setItemAnimator(itemAnimator);
setLayoutManager(layoutManager);
adapter.setLayoutManager(layoutManager);
adapter.setStyle(messagesListStyle);
addOnScrollListener(new RecyclerScrollMoreListener(layoutManager, adapter));
super.setAdapter(adapter);
}
I ideally do not want to set up a keyboard listener and programatically scroll to the bottom every time the keyboard is shown/hidden. It seems that I must be doing something wrong somewhere. Any ideas?
Upvotes: 8
Views: 1355
Reputation: 1493
When implementing the android ui chat, I spent a long time looking for a solution to the problem with scrolling messages when the keyboard opens. Basically, the decisions were based on scrolling through the recycler to the height of the keyboard and it looked like a crutch.
As it turned out, you need only few things
1. Do not use layoutManager.stackFromEnd = true
2. Do not use ConstraintLayout with high 0dp as a recycler parent
2. Do not use RelativeLayout with wrap_content height as a recycler parent
Setting example:
val adapter = MessagesAdapter ()
val layoutManager = LinearLayoutManager (this, RecyclerView.VERTICAL, true)
rvMessages.layoutManager = layoutManager
rvMessages.adapter = adapter
For layout you can use LinearLayout, RelativeLayout or ConstraintLayout with match_parent height and padding from bottom to editText height.
<LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android"
android: layout_width = "match_parent"
android: layout_height = "match_parent"
android: orientation = "vertical">
<androidx.recyclerview.widget.RecyclerView
android: id = "@ + id / rvMessages"
android: layout_width = "match_parent"
android: layout_height = "0dp"
android: layout_weight = "1" />
<EditText
android: id = "@ + id / etMessage"
android: layout_width = "match_parent"
android: layout_height = "wrap_content" />
</LinearLayout>
Upvotes: 3