M.Waqas Pervez
M.Waqas Pervez

Reputation: 2430

ActionBar is scrolled up when using adjustpan

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>

With AdjustResize

enter image description here

Upvotes: 1

Views: 2078

Answers (2)

Tayyab Mazhar
Tayyab Mazhar

Reputation: 1712

The accepted answer didn't work for me. This works:

In your activity tag in manifest, add android:windowSoftInputMode="adjustResize".

In onCreate method of your activity add this:

View.OnLayoutChangeListener layoutChangeListener = new View.OnLayoutChangeListener()
{
    @Override
    public void onLayoutChange(View v, int left, final int top, int right, final int bottom,
                        int oldLeft, final int oldTop, int oldRight, final int oldBottom)
    {
        if (oldBottom != 0)
        {
            //when softkeyboard opens, the height of layout get's small, and when softkeyboa
            //-rd closes the height grows back(gets larger).We can find the change of height
            // by doing oldBotton - bottom, and the result of subtraction is how much we nee
            //-d to scroll. Change of height is positive if keyboard is opened, and negative
            //if it's closed.
            int pixelsToScrollVertically = oldBottom - bottom;
            recyclerView.scrollBy(0, pixelsToScrollVertically);
        }
    }
};


myAdapter = new MyAdapter();
recyclerView.setAdapter(myAdapter);

recyclerView.addOnLayoutChangeListener(layoutChangeListener);

Upvotes: 1

Nicolas Tyler
Nicolas Tyler

Reputation: 10552

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

Upvotes: 1

Related Questions