I have been stuck into this for quite some time. I am trying to develop a chat module. I have been stuck into this part where when the SoftInputKeyboard
overlays the content of the RecyclerView
. I have tried almost every combination of adjustResize
and adjustPan
with stateHidden
and stateVisible
with no success at all.
On Using adjustPan
the ActionBar
gets hidden along with 2-3 recyclerview
items.
I have attached screenshots. Any help with be appreciated.
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/light_grey"
android:fitsSystemWindows="true"
android:focusable="true"
android:focusableInTouchMode="true">
<LinearLayout
android:id="@+id/listFooter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="8dp"
android:orientation="horizontal">
<EditText
android:id="@+id/messageInput"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/white"
android:hint="Write a message"
android:inputType="textMultiLine"
android:padding="16dp"
android:textSize="14sp" />
<ImageView
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
android:contentDescription="@null"
android:padding="12dp"
android:src="@drawable/ic_send" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview_chat_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/listFooter"
android:layout_marginTop="8dp" />
</RelativeLayout>
The android:windowSoftInputMode
does not scroll your content for you when the keyboard is shown/hidden.
The documentation says:
adjustResize - The activity's main window is always resized to make room for the soft keyboard on screen.
adjustPan - The activity's main window is not resized to make room for the soft keyboard. Rather, the contents of the window are automatically panned so that the current focus is never obscured by the keyboard and users can always see what they are typing. This is generally less desirable than resizing, because the user may need to close the soft keyboard to get at and interact with obscured parts of the window.
Basically this means that adjustResize
makes your rootview smaller and puts the softKeyboard below it. And adjustPan
pushes the top half of the rootview out of the screen to make room for the the softKeyboard.
I would suggest using adjustResize
because it wont push your Toolbar out of the screen. Then you would have to scroll the content yourself. Its easier said than done obviously, but there are methods built in to do this.
First you would have to get the last visible item position in the recyclerview.
//class variable
private int lastVisiblePosition = 0;
@Override
protected void onCreate(Bundle savedInstanceState)
{
//...
recyclerview_chat_main.addOnScrollListener(new RecyclerView.OnScrollListener()
{
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
super.onScrolled(recyclerView, dx, dy);
lastVisiblePosition = ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPosition();
}
});
//...
}
Then you have to do is scroll to that item when the SoftKeyboard is shown, the issue with that is there is no built in way to get when the keyboard is shown, fortunately someone has already addressed that here: https://stackoverflow.com/a/25681196/2027232
using Jaap's answer we could add something like this:
//class variables
private ViewGroup rootLayout = null;
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
//...
ViewGroup rootLayout = (ViewGroup)findViewById(android.R.id.content);
keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight();
int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getHeight();
if(heightDiff > contentViewTop)
{
recyclerview_chat_main.getLayoutManager().scrollToPosition(lastVisiblePosition);
}
}
};
rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener);
//...
}
And lastly dont forget to remove the global listener when the activity gets destroyed:
@Override
protected void onDestroy()
{
super.onDestroy();
if(rootLayout != null && keyboardLayoutListener != null)
rootLayout.getViewTreeObserver().removeOnGlobalLayoutListener(keyboardLayoutListener);
}