logo

Google announced new Android layout called “ConstraintLayout” in IO 2016. Currently it is in Alpha release. Good news about ConstraintLayout is it is compatible with API level 9 :).

Google introduced ConstraintLayout for two main reasons:

  1. Ease with which Android UI can be designed
  2. Performance improvement in case of nesting layouts

Though, it really helps developer by making Android UI designing easier simply by drag & drop, but it is still far from the performance improvements Google hopes to achieve. But, ConstraintLayout is still in alpha and Google is iterating fast and solving the bugs reported. At the time of writing, it is at alpha-3.

To check the performance, I used the following layout UI from “constraint-layout-master” project from Google CodeLabs.

Screenshot_20160707-160243

 

I used following XML from Google code labs using ConstraintLayout.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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:id="@+id/activity_main_done"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_editor_absoluteX="0dp"
    app:layout_editor_absoluteY="80dp"
    tools:layout_editor_absoluteX="0dp"
    tools:layout_editor_absoluteY="80dp">

    <ImageView
        android:src="@drawable/singapore"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_editor_absoluteX="0dp"
        app:layout_editor_absoluteY="0dp"
        android:id="@+id/header"
        android:scaleType="centerCrop"
        android:contentDescription="@string/dummy"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintTop_creator="1"
        app:layout_constraintRight_creator="1"
        app:layout_constraintBottom_creator="1"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main_done"
        tools:layout_constraintLeft_creator="1"
        app:layout_constraintTop_toTopOf="@+id/activity_main_done"
        tools:layout_constraintTop_creator="1"
        app:layout_constraintRight_toRightOf="@+id/activity_main_done"
        tools:layout_constraintRight_creator="1"
        app:layout_constraintBottom_toBottomOf="@+id/favorite"
        android:layout_marginBottom="16dp"
        tools:layout_constraintBottom_creator="1"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintVertical_bias="0.0" />

    <ImageView
        android:src="@drawable/ic_star"
        android:layout_width="36dp"
        android:layout_height="36dp"
        app:layout_editor_absoluteX="359dp"
        app:layout_editor_absoluteY="104dp"
        android:id="@+id/favorite"
        android:background="@drawable/info_background"
        android:padding="5dp"
        android:contentDescription="@string/dummy"
        app:layout_constraintTop_creator="1"
        app:layout_constraintRight_creator="1"
        app:layout_constraintBottom_creator="0"
        app:layout_constraintTop_toTopOf="@+id/activity_main_done"
        app:layout_constraintRight_toRightOf="@+id/activity_main_done"
        android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/activity_main_done"
        android:layout_marginBottom="16dp"
        app:layout_constraintVertical_bias="0.19" />

    <TextView
        android:text="@string/singapore"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_editor_absoluteX="16dp"
        app:layout_editor_absoluteY="140dp"
        android:id="@+id/title"
        android:textSize="24sp"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintTop_creator="0"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main_done"
        android:layout_marginStart="16dp"
        app:layout_constraintTop_toBottomOf="@+id/header"
        android:layout_marginTop="16dp" />

    <EditText
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:text="@string/camera_value"
        android:ems="10"
        app:layout_editor_absoluteX="73dp"
        app:layout_editor_absoluteY="176dp"
        android:id="@+id/cameraType"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintTop_creator="1"
        app:layout_constraintRight_creator="1"
        app:layout_constraintLeft_toLeftOf="@+id/settings"
        tools:layout_constraintLeft_creator="1"
        app:layout_constraintTop_toBottomOf="@+id/title"
        android:layout_marginTop="8dp"
        app:layout_constraintRight_toRightOf="@+id/settings"
        tools:layout_constraintRight_creator="1" />

    <TextView
        android:text="@string/camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_editor_absoluteX="16dp"
        app:layout_editor_absoluteY="189dp"
        android:id="@+id/cameraLabel"
        android:labelFor="@+id/cameraType"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintBaseline_creator="1"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main_done"
        android:layout_marginStart="16dp"
        app:layout_constraintBaseline_toBaselineOf="@+id/cameraType" />

    <TextView
        android:text="@string/settings"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_editor_absoluteX="16dp"
        app:layout_editor_absoluteY="238dp"
        android:id="@+id/settingsLabel"
        android:labelFor="@+id/settings"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintBaseline_creator="1"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main_done"
        android:layout_marginStart="16dp"
        app:layout_constraintBaseline_toBaselineOf="@+id/settings" />

    <EditText
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:text="@string/camera_settings"
        android:ems="10"
        app:layout_editor_absoluteX="73dp"
        app:layout_editor_absoluteY="225dp"
        android:id="@+id/settings"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintTop_creator="1"
        app:layout_constraintRight_creator="1"
        app:layout_constraintLeft_toRightOf="@+id/settingsLabel"
        android:layout_marginStart="6dp"
        tools:layout_constraintLeft_creator="1"
        app:layout_constraintTop_toBottomOf="@+id/cameraType"
        android:layout_marginTop="8dp"
        app:layout_constraintRight_toRightOf="@+id/description"
        tools:layout_constraintRight_creator="1" />

    <Button
        android:text="@string/upload"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_editor_absoluteX="307dp"
        app:layout_editor_absoluteY="538dp"
        android:id="@+id/upload"
        app:layout_constraintRight_creator="1"
        app:layout_constraintBottom_creator="1"
        app:layout_constraintRight_toRightOf="@+id/activity_main_done"
        android:layout_marginEnd="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/activity_main_done"
        android:layout_marginBottom="16dp" />

    <Button
        android:text="@string/discard"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_editor_absoluteX="211dp"
        app:layout_editor_absoluteY="538dp"
        android:id="@+id/discard"
        android:elevation="0dp"
        app:layout_constraintRight_creator="0"
        app:layout_constraintBaseline_creator="1"
        app:layout_constraintRight_toLeftOf="@+id/upload"
        android:layout_marginEnd="8dp"
        app:layout_constraintBaseline_toBaselineOf="@+id/upload" />

    <TextView
        android:text="@string/singapore_description"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_editor_absoluteX="16dp"
        app:layout_editor_absoluteY="274dp"
        android:id="@+id/description"
        android:fadingEdge="vertical"
        android:ellipsize="end"
        android:textSize="15sp"
        app:layout_constraintLeft_creator="1"
        app:layout_constraintTop_creator="0"
        app:layout_constraintRight_creator="1"
        app:layout_constraintBottom_creator="0"
        app:layout_constraintLeft_toLeftOf="@+id/activity_main_done"
        android:layout_marginStart="16dp"
        tools:layout_constraintLeft_creator="1"
        app:layout_constraintTop_toBottomOf="@+id/settings"
        android:layout_marginTop="8dp"
        tools:layout_constraintTop_creator="1"
        app:layout_constraintRight_toRightOf="@+id/activity_main_done"
        android:layout_marginEnd="16dp"
        tools:layout_constraintRight_creator="1"
        app:layout_constraintBottom_toTopOf="@+id/discard"
        android:layout_marginBottom="8dp"
        tools:layout_constraintBottom_creator="1" />
</android.support.constraint.ConstraintLayout>

I also created similar UI using RelativeLayout. Following is XML

<?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:id="@+id/relativeLayout">
    <ImageView android:id="@+id/header"
        android:layout_width="match_parent"
        android:layout_height="140dp"
        android:scaleType="centerCrop"
        android:src="@drawable/singapore"/>
    <ImageView android:id="@+id/ic_star"
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:layout_below="@+id/header"
        android:layout_marginTop="-18dp"
        android:background="@drawable/info_background"
        android:src="@drawable/ic_star"
        android:layout_alignParentRight="true"
        android:layout_marginRight="16dp"
        android:padding="5dp"/>
    <TextView android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/header"
        android:layout_marginTop="16dp"
        android:layout_marginLeft="16dp"
        android:text="SINGAPORE"/>
    <LinearLayout android:id="@+id/cameraLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="8dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <TextView android:id="@+id/cameraLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Camera"/>
        <EditText android:id="@+id/cameraType"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <LinearLayout android:id="@+id/settingsLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/cameraLayout"
        android:layout_marginTop="8dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <TextView android:id="@+id/settingsLabel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Settings"/>
        <EditText android:id="@+id/settingsType"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <TextView android:id="@+id/description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/settingsLayout"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginTop="8dp"
        android:text="@string/singapore_description"/>
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/description"
        android:layout_marginTop="8dp"
        android:gravity="right"
        android:padding="8dp"
        android:orientation="horizontal">
        <Button android:id="@+id/btn1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button1"/>
        <Button android:id="@+id/btn2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:text="Button2"/>
    </LinearLayout>
</RelativeLayout>

Checked the performance using hierarchical viewer on Moto-G3 running Android 6.0.1. It is as follows.

Performance using RelativeLayout

Rendering time using RelativeLayout

Performance using ConstraintLayout

Rendering time using ConstraintLayout alpha3

 

Measurement in ConstraintLayout (9.053 ms) took roughly 10 times as it is for RelativeLayout (0.854 ms). ConstraintLayout seems doing much calculations to measure where to place child. So, performance is still far, but still ConstraintLayout is at alpha and hopefully over time, it will achieve best performance.

UPDATE – constraint-layout-alpha4

Quite good jump in performance improvement in alpha4. Now measurement almost take half time which was taking in alpha3. Previously in alpha3 it took 9ms, in alpha4 it took 4.1ms.. Seems like quite good performance improvement..

Rendering time using ConstraintLayout alpha4

Rendering time using ConstraintLayout alpha4

AUTHOR: Mahavir Jain

Founder @CodeToArt, Leads Android Development at CodeToArt.

No Comments

Leave a Comment

Your email address will not be published.