Home > OS >  LinearLayout with adjustResize
LinearLayout with adjustResize

Time:08-01

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)

CodePudding user response:

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>
  • Related