Issue
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:
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:
- GridLayout, hides the input field under the keyboard
- FrameLayout, places the input field on top of the ListView (messages)
Solution
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>
Answered By - Sergei Kozelko
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.