androidandroid-layoutandroid-linearlayoutnestedlayout

Android - Put two EditTexts in one line in vertical Linear Layout


I have a vertical Linear Layout with some elements, but at one position I want 2 EditTexts in 1 row. I did it with a horizontal Linear Layout in it, but Android Studio says that this is very bad for performance.

Is there a way of doing this without nested layouts? (XML or programmatically)

XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/cyan_50"
android:orientation="vertical"
tools:context="com.secutschett.RegisterActivity"
android:weightSum="100">

<android.support.design.widget.AppBarLayout
    android:layout_width="fill_parent"
    android:layout_height="?attr/actionBarSize"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="fill_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/cyan_700"
        app:popupTheme="@style/AppTheme.PopupOverlay"
        app:title="@string/app_name"
        app:titleTextColor="@color/cyan_50" />

</android.support.design.widget.AppBarLayout>

<TextView
    android:id="@+id/step1TextView"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:text="@string/step1TextViewText"
    android:textAppearance="@style/TextAppearance.AppCompat.Headline" />

<TextView
    android:id="@+id/placeholder1"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10" />

<EditText
    android:id="@+id/step1UsernameEditText"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:hint="@string/step1UsernameEditTextHint"
    android:inputType="text"
    android:maxLines="1"
    android:textAppearance="@style/TextAppearance.AppCompat"
    android:textColorHint="@color/blue_grey_400" />

<EditText
    android:id="@+id/step1NicknameEditText"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:hint="@string/step1NicknameEditTextHint"
    android:inputType="text"
    android:maxLines="1"
    android:textAppearance="@style/TextAppearance.AppCompat"
    android:textColorHint="@color/blue_grey_400" />

<TextView
    android:id="@+id/placeholder2"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10" />

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/step1PasswordEditText"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="50"
        android:hint="@string/step1PasswordEditTextHint"
        android:inputType="text|textPassword"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textColorHint="@color/blue_grey_400" />

    <EditText
        android:id="@+id/step1RepeatPasswordEditText"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="50"
        android:hint="@string/step1RepeatPasswordEditTextHint"
        android:inputType="text|textPassword"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textColorHint="@color/blue_grey_400" />
</LinearLayout>

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/step1EmailAddressEditText"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="50"
        android:hint="@string/step1EmailAddressEditTextHint"
        android:inputType="text|textEmailAddress"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textColorHint="@color/blue_grey_400" />

    <EditText
        android:id="@+id/step1RepeatEmailAddressEditText"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="50"
        android:hint="@string/step1RepeatEmailAddressEditTextHint"
        android:inputType="text|textEmailAddress"
        android:maxLines="1"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textColorHint="@color/blue_grey_400" />
</LinearLayout>

<TextView
    android:id="@+id/placeholder3"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10" />

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:orientation="horizontal">

    <Button
        android:id="@+id/step1RegisterButton"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="30"
        android:text="@string/registerButtonName" />

    <TextView
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="10" />

    <CheckBox
        android:id="@+id/step1AgreeCheckBox"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="10" />

    <TextView
        android:id="@+id/step1PoliciesTextView"
        android:layout_width="0dip"
        android:layout_height="fill_parent"
        android:layout_weight="50"
        android:maxLines="10"
        android:text="@string/step1PoliciesTextViewText"
        android:textColorLink="@color/blue_500" />

</LinearLayout>

<com.roide.progressdotslib.ProgressDotWidget
    android:id="@+id/progress_dots1"
    android:layout_width="fill_parent"
    android:layout_height="0dip"
    android:layout_weight="10"
    android:background="@color/cyan_600"
    android:padding="@dimen/standard_margins" />

</LinearLayout>

How it should look


Solution

  • Android Studio says that this is very bad for performance.

    Don't worry about this warning.

    It is true that nested layouts are more expensive (in terms of time it takes the system to render them and memory to hold the View objects), but a few nested views are not going to have any noticeable negative impact on your app's performance. Usually, the only place you really have to worry about nested views is when you're using a deeply-nested hierarchy inside each item for ListView or RecyclerView.

    Here is a Google blog post where they talk about the performance benefits of using ConstraintLayout to create a completely flat view hierarchy: https://android-developers.googleblog.com/2017/08/understanding-performance-benefits-of.html

    If you scroll to the very end, you'll see that the flat hierarchy takes about 0.5 ms to draw, and the nested one takes about 0.7 ms to draw. This is a large relative difference, but in terms of absolute speed you are well within the safe window at 0.7 ms.

    Is there a way of doing this without nested layouts? (XML or programmatically)

    Yes. You could do it using ConstraintLayout. There are plenty of developer guides for ConstraintLayout, so I won't go into detail here.

    Using this will give you all the performance benefits mentioned above. The cost to doing so is that your XML code will be slightly more complex. Adding a new row in the middle of your existing rows will mean you have to make more changes to what you already have, as opposed to dropping the new row in and being done. This isn't a large cost, to be sure, but it is something to consider.