0

I have a layout like this in a page of a View Pager:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/black">
    <LinearLayout
        android:id="@+id/bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_alignParentTop="true"
        android:orientation="horizontal"
        android:gravity="center"
        android:background="@drawable/background_gray">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="16sp"
            android:paddingTop="15dp"
            android:paddingBottom="15dp"
            android:paddingLeft="3dp" />
    </LinearLayout>
    <RelativeLayout
        android:id="@+id/container_chat_box"
        android:background="@drawable/conversation_background_gray"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="50dp">
        <EditText
            android:id="@+id/chat_box"
            style="@style/ConversationChatBox" />
    </RelativeLayout>
    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/bar"
        android:background="@android:color/white"
        android:stackFromBottom="true"
        android:transcriptMode="normal"
        android:layout_above="@id/chat_box"
        android:paddingBottom="15dp"
        android:clipToPadding="false"
        android:divider="@null"
        android:dividerHeight="0dp"
        android:listSelector="@android:color/transparent" />
</RelativeLayout>

This is an idea of how It looks like:

----------
[   bar   ]
[list view]
[list view]
[list view]
[list view]
[edit text]

When I click on the edit text, I'd like the bar to stay where it is (at the top of the screen), but the list view to be pushed up, so it looks like:

------------
[   bar   ]
[list view]
[list view]
[edit text]
[keyboard ]

What I get (the bar is pushed up and disappears):

------------
[list view]
[list view]
[list view]
[edit text]
[keyboard ]

I have this on my AndroidManifest:

android:windowSoftInputMode="adjustPan"

I tried different combinations of values for setting android:windowSoftInputMode, but I either get the keyboard to appear covering the edit text or the whole screen pushed up.

Is there a way to keep the bar in place while the listview is pushed up? Thank you in advance.

Marilia
  • 1,691
  • 1
  • 16
  • 26
  • Try to set android:layout_height="match_parent" for the ListView – TpoM6oH Jul 10 '15 at 22:48
  • Thank you for the reply. That didn't change the layout tho. I wonder if the issue is related to using android:layout_alignParentTop="true" in the bar Linear Layout. But I can't think of a more correct way to keep the bar at the top of the screen. – Marilia Jul 11 '15 at 00:12
  • I changed the soft input mode to: android:windowSoftInputMode="adjustResize" and added android:fitsSystemWindows="true" to the outer layout. Followed some code from [this post](http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible) and now all works except for a black back that appears at the bottom (since the workaround in the post only fixes the top, left and right margins). – Marilia Jul 14 '15 at 00:31
  • Actually, the CustomInsetsLayout idea from [this post](http://stackoverflow.com/questions/21092888/windowsoftinputmode-adjustresize-not-working-with-translucent-action-navbar) was the inspiration for the work around. Still have to figure It out how to remove the black bar at the bottom of the screen now. – Marilia Jul 14 '15 at 00:42

1 Answers1

0

I was able to solve the issue, although only tested in a few phones so far.

That's the solution:

1) Change soft input mode to android:windowSoftInputMode="adjustResize" and add android:fitsSystemWindows="true" to the layout root view.

2) Created a CustomInsetsLayout class that extends RelativeLayout (code bellow), so I can control what happens with the layout when the screen resizes.

3) At this point I had an undesired black bar at the bottom of the layout. That bar was the margin bottom that was supposed to be hidden under the navigation bar but the FULLSCREEN flags responsible for that don't work with adjustResize. So I had to add code to the CustomInsetsLayout to remove the bottom margin from the root view when the screen resizes.

That's how the CustomInsetsLayout class looks like (references and notes in the class description):

package com.playchat.ui.full;

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.WindowInsets;
import android.widget.RelativeLayout;

/**
 * http://stackoverflow.com/questions/21092888/windowsoftinputmode-adjustresize-not-working-with-translucent-action-navbar
 *
 * @author Kevin
 *         Date Created: 3/7/14
 *
 * https://code.google.com/p/android/issues/detail?id=63777
 *
 * When using a translucent status bar on API 19+, the window will not
 * resize to make room for input methods (i.e.
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are
 * ignored).
 *
 * To work around this; override {@link #fitSystemWindows(android.graphics.Rect)},
 * capture and override the system insets, and then call through to FrameLayout's
 * implementation.
 *
 * For reasons yet unknown, modifying the bottom inset causes this workaround to
 * fail. Modifying the top, left, and right insets works as expected.
 */
public class CustomInsetsLayout extends RelativeLayout {
    private int[] mInsets = new int[4];

    public CustomInsetsLayout(Context context) {
        super(context);
    }

    public CustomInsetsLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomInsetsLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public final int[] getInsets() {
        return mInsets;
    }

    @Override
    protected final boolean fitSystemWindows(Rect insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Intentionally do not modify the bottom inset. For some reason,
            // if the bottom inset is modified, window resizing stops working.
            // TODO: Figure out why.
            mInsets[0] = insets.left;
            mInsets[1] = insets.top;
            mInsets[2] = insets.right;

            insets.left = 0;
            insets.top = 0;
            insets.right = 0;

            if (insets.bottom > 0) {
                // Remove bottom margin from the root view
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
                params.bottomMargin = 0;
                setLayoutParams(params);

            }
        }

        return super.fitSystemWindows(insets);
    }

    @Override
    public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
            if (insets.getSystemWindowInsetBottom() > 0) {
                // Remove bottom margin from the root view
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams();
                params.bottomMargin = 0;
                setLayoutParams(params);

            }
            mInsets[0] = insets.getSystemWindowInsetLeft();
            mInsets[1] = insets.getSystemWindowInsetTop();
            mInsets[2] = insets.getSystemWindowInsetRight();
            return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
                insets.getSystemWindowInsetBottom()));

        } else {
            return insets;
        }
    }
}
Marilia
  • 1,691
  • 1
  • 16
  • 26