Wassim Beltaief

ConstraintLayout and flat hierarchies

Thursday, October 5, 2017

I spend a lot of time building layouts with nested LinearLayouts. A horizontal one inside a vertical one inside another horizontal one. It works but Hierarchy Viewer shows how deep the tree goes. Deep hierarchies mean more measure passes, slower rendering.

RelativeLayout helps a little, you can position things relative to each other without nesting. But it has limits, especially for complex screens.

ConstraintLayout solves this.

The idea

Every view declares constraints to its parent or to siblings. The layout engine resolves everything in one pass without nesting.

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_margin="16dp"
        android:text="Title" />

    <TextView
        android:id="@+id/subtitle"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@id/title"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="Subtitle" />

</androidx.constraintlayout.widget.ConstraintLayout>

layout_width="0dp" means "match the constraints". Both start and end are constrained to parent, so the view stretches to fill the width. This replaces match_parent from inside a ConstraintLayout.

Chains

Chains let you distribute views along an axis. Horizontal chain with three buttons:

app:layout_constraintHorizontal_chainStyle="spread"

Three styles: spread distributes evenly, spread_inside puts space between views but not at edges, packed groups them in the center. For a button bar this replaces a horizontal LinearLayout completely.

Bias

Bias positions a view between its two constraints. 0.0 means all the way to the start, 1.0 all the way to the end, 0.5 centered.

app:layout_constraintHorizontal_bias="0.3"

The view sits 30% from the left. Useful for asymmetric layouts that are hard to express any other way.

Guidelines

A Guideline is an invisible line at a fixed position or percentage of the parent. Other views can constrain to it.

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.5" />

A vertical guideline at 50%. Now you can have two equal columns without a LinearLayout and without hardcoded sizes.

The editor

Android Studio has a visual editor for ConstraintLayout that is actually good. You can drag handles to create constraints. But I mostly write XML directly because the editor sometimes generates redundant constraints that are hard to understand.

Worth learning

The first few layouts in ConstraintLayout are slow. You have to think differently. But the resulting XML is flat and the layouts measure faster.

For any complex screen, ConstraintLayout is the right choice now.