Vadim Hagedorn
Vadim Hagedorn

Reputation: 154

LinearLayout with adjustResize

Prelude

For practice, I'm attempting to copy Apple's iMessage.

I'm using nested LinearLayouts for the message bubbles and the input bar, however the problem is when the keyboard pops up. I have it set to use adjustResize, but different screen aspect ratios mess everything up when using LinearLayout weights.

Problem

The same weight on different screens: Google Pixel 4a Motorola XT1609

Code

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android = "http://schemas.android.com/apk/res/android"
        android:layout_width = "match_parent"
        android:layout_height = "match_parent"
        android:background = "@color/bg"
        android:focusableInTouchMode = "true">

    <LinearLayout
            android:orientation = "vertical"
            android:layout_width = "match_parent"
            android:layout_height = "match_parent">

        <ListView
                android:id = "@+id/history"
                android:layout_width = "match_parent"
                android:layout_height = "0dp"
                android:layout_weight = "8"
                android:divider = "@color/bg"/>

        <LinearLayout
                android:orientation = "horizontal"
                android:layout_width = "match_parent"
                android:layout_height = "0dp"
                android:paddingHorizontal="15dp"
                android:paddingVertical="5dp"
                android:layout_weight="1"
                >

            <ImageButton
                    android:id = "@+id/imageButton"
                    android:layout_width = "0dp"
                    android:layout_height = "wrap_content"
                    android:scaleType = "fitXY"
                    android:layout_gravity = "center"
                    android:padding = "20dp"
                    android:adjustViewBounds = "true"
                    android:background = "@drawable/ic_photo_camera"
                    android:contentDescription = "@string/camera"
                    android:layout_weight = "1" />


            <LinearLayout
                    android:orientation = "horizontal"
                    android:layout_width = "0dp"
                    android:layout_height = "wrap_content"
                    android:layout_gravity="center"
                    android:background = "@drawable/input_bg"
                    android:layout_weight = "6">

                <EditText
                        android:id = "@+id/editText"
                        android:layout_width = "0dp"
                        android:layout_height = "wrap_content"
                        android:minHeight="48dp"
                        android:layout_weight="5"
                        android:layout_gravity="center"
                        android:inputType = "text"
                        android:ems = "10"
                        android:hint = "@string/imessage"
                        android:paddingHorizontal = "10dp"
                        android:textColor="@color/fg_white"
                        android:textColorHint="@color/fg_dark"
                        android:text = "" />


                <ImageButton
                        android:id="@+id/sendButton"
                        android:layout_width = "0dp"
                        android:layout_height = "wrap_content"
                        android:layout_weight="1"
                        android:layout_gravity = "center"
                        android:scaleType = "centerInside"
                        android:adjustViewBounds = "true"
                        android:background = "@null"
                        android:scaleX = "1.5"
                        android:scaleY = "1.5"
                        android:src = "@drawable/send_arrow"
                        android:contentDescription = "@string/send" />

            </LinearLayout>

        </LinearLayout>


    </LinearLayout>


</RelativeLayout>

Question

How can I make a flexible input field that moves up and down when the keyboard opens without distoring? I've tried adjustPan but it isn't really a good solution.

Other layouts I have tried:

  1. GridLayout, hides the input field under the keyboard
  2. FrameLayout, places the input field on top of the ListView (messages)

Upvotes: 0

Views: 82

Answers (1)

Sergei Kozelko
Sergei Kozelko

Reputation: 833

I think your problem is caused by using weights everywhere. Not only it causes your elements to change size depending on screen size, it can also cause performance problems.

Here's a simpler layout, that should look good regardless of screen size. Notice how only elements that need to fill all available space have weight - ListView vertically and EditText with its container horizontally. Images need only enough space to display themselves, so wrap_content is used. Same with bottom LinearLayout vertically. After their sizes are calculated, remaining space will be filled according to the weights.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android = "http://schemas.android.com/apk/res/android"
    android:orientation = "vertical"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:background = "@color/bg"
    android:focusableInTouchMode = "true">

    <ListView
        android:id = "@+id/history"
        android:layout_width = "match_parent"
        android:layout_height = "0dp"
        android:layout_weight = "1"
        android:divider = "@color/bg"/>

    <LinearLayout
        android:orientation = "horizontal"
        android:layout_width = "match_parent"
        android:layout_height = "wrap_content"
        android:paddingHorizontal="15dp"
        android:paddingVertical="5dp">

        <ImageButton
            android:id = "@+id/imageButton"
            android:layout_width = "wrap_content"
            android:layout_height = "wrap_content"
            android:scaleType = "fitXY"
            android:layout_gravity = "center"
            android:padding = "20dp"
            android:adjustViewBounds = "true"
            android:background = "@drawable/ic_photo_camera"
            android:contentDescription = "@string/camera" />


        <LinearLayout
            android:orientation = "horizontal"
            android:layout_width = "0dp"
            android:layout_height = "wrap_content"
            android:layout_gravity="center"
            android:background = "@drawable/input_bg"
            android:layout_weight = "1">

            <EditText
                android:id = "@+id/editText"
                android:layout_width = "0dp"
                android:layout_height = "wrap_content"
                android:minHeight="48dp"
                android:layout_weight="1"
                android:layout_gravity="center"
                android:inputType = "text"
                android:ems = "10"
                android:hint = "@string/imessage"
                android:paddingHorizontal = "10dp"
                android:textColor="@color/fg_white"
                android:textColorHint="@color/fg_dark"
                android:text = "" />

            <ImageButton
                android:id="@+id/sendButton"
                android:layout_width = "wrap_content"
                android:layout_height = "wrap_content"
                android:layout_gravity = "center"
                android:scaleType = "centerInside"
                android:adjustViewBounds = "true"
                android:background = "@null"
                android:scaleX = "1.5"
                android:scaleY = "1.5"
                android:src = "@drawable/send_arrow"
                android:contentDescription = "@string/send" />

        </LinearLayout>
    </LinearLayout>
</LinearLayout>

Upvotes: 1

Related Questions