Relative Layout is Dead. Meet Constraint Layout — Part 1

Paul Gillis
QuarkWorks, Inc.
Published in
5 min readNov 8, 2018

--

There are 3.3 million apps on the Google Play store. For an app to be noticed you have to be the best. Building an Android UI that looks great on multiple devices can be frustrating. What if we made it easy?

Why Constraint Layout instead of other Layouts?

I see developers stick to RelativeLayout because it’s what they know, but they are missing out on great features that simplify advanced layouts. Features like view chaining, position bias, barriers and guidelines can make a layout that you previously had to break down into multiple sub views or xml files into a condensed layout. If that doesn’t convince you, Google has marked RelativeLayout as legacy code, and current documentation on it redirects to ConstraintLayout.

Constraining Views

There are four sides to a view: Start, End, Top, Bottom (Assuming api 19+).

To constrain or position a view, pick a side of the view. app:layout_constraint{SideOfCurrentView}

Then pick a side of the view it should be relative to. app:layout_constraintTop_to{SideRelativeView}Of="{RelativeViewId}"

For example, let's put a TextView’s top to be to the bottom of a blue square view.

<View 
android:id="@+id/myView"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@color/colorPrimary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintTop_toBottomOf="@id/myView"

tools:text="Hello world"
android:textSize="42sp" />
TextView below myView

Centering Views

Previously, to center a view in a RelativeLayout you would write centerInParent=true. Constraint Layout instead allows centering in-between views and the parent. Constrain the start to the parent’s start and the end to the parent’s end. This will center the view horizontally.

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"

tools:text="Hello world"
android:textSize="42sp" />
Horizontally Centered TextView

Vertical and Horizontal Bias

Bias is the percentage of space on the Start/Top side of a view. All centered views actually have a bias of 0.5 by default. This can be adjusted to move the view from the start (horizontal bias of 0) to the end (horizontal bias of 1). The same can be done for a vertical center. A vertical bias of 0 will put the view below its top constraint and a bias of 1 will put the view above its bottom constraint.

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
tools:text="Hello world"
android:textSize="42sp" />
Horizontal Bias = 0%

Sizing Views

All child views need a size. There are three ways to size the child views.

  1. match_parent — Match parent will be the same size as the ConstraintLayout. It will still use margins and padding.
  2. wrap_content — Wrap content only uses the smallest space required. If there are no constraints, margins aren’t used. (Example: marginStart needs a constraintStart)
  3. 0dp — Match constraint will make the view take up the entire space the constraints allow.

For an example, let’s use a text box in the top left corner with some margins and center a TextView Horizontally between the checkbox’s end and parent’s end. Now we can compare the different sizes using the TextView.

<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"

android:layout_marginStart="20dp"
android:layout_marginTop="20dp" />

<TextView
android:layout_width="match_parent/wrap_content/0dp"
android:layout_height="wrap_content"

app:layout_constraintStart_toEndOf="@id/checkBox"
app:layout_constraintEnd_toEndOf="parent"
//This makes the textView's vertical center the same as checkbox
app:layout_constraintTop_toTopOf="@id/checkBox"
app:layout_constraintBottom_toBottomOf="@id/checkBox"

android:background="@color/colorPrimary"
android:text="Hello world"
android:textSize="42sp" />
TextView width = match_parent
TextView width = wrap_content
TextView width = 0dp (match_constraint)

Chaining Views

Chaining views vertically or horizontally groups views and determines filling the space in one of four ways.

  1. Spread (Default) — Views are spaced equally between start/end or top/bottom constraints of the chain.
  2. Spread Inside — Views are spread the furthest apart from each other as far as the start/end or top/bottom constraints allow.
  3. Weighted — Like LinearLayout weight, each view has a weight in the chain to determine how much space each view gets. (Weight of a chain is defined by layout_constraintHorizontal_weight or layout_constraintVertical_weight.) Weighted is not a chainStyle.
  4. Packed — All the views in the chain are squished together and the chain of views is spaced between the start/end or top/bottom constraints.
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/helloTextView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_chainStyle="spread"

android:layout_marginStart="20dp"
android:layout_marginTop="20dp" />

<TextView
android:id="@+id/helloTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

app:layout_constraintStart_toEndOf="@id/checkBox"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/checkBox"
app:layout_constraintBottom_toBottomOf="@id/checkBox"

android:background="@color/colorPrimary"
android:text="Hello world"
android:textSize="42sp" />
Horizontal Chain Style = spread
Horizontal Chain Style = spread_inside
Horizontal Chain Style = packed

Weighted Chains

Weighted chains aren’t like the other three chain styles — they aren’t even a chain style. Instead, set the views in the chain to 0dp (match_constraint). Then set the horizontal or vertical weight for the views. Let’s use the previous example with the checkbox and textview. I’ve set both views to equal weights and removed the marginStart to show how a weight of 1:1 will give both views half the width of the parent.

<CheckBox
android:id="@+id/checkBox"
android:layout_width="0dp"
android:layout_height="wrap_content"

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/helloTextView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_weight="1"

android:layout_marginTop="20dp" />

<TextView
android:id="@+id/helloTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"

app:layout_constraintStart_toEndOf="@id/checkBox"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/checkBox"
app:layout_constraintBottom_toBottomOf="@id/checkBox"
app:layout_constraintHorizontal_weight="1"

android:background="@color/colorPrimary"
android:text="Hello world"
android:textSize="42sp" />
Weighted Chain of 1:1

Find out more

I’m in the process of writing a second part on the extra features of constraint layout! Follow us on medium to get updates! If you can’t wait that long, you can check out Android’s constraint layout guide.

As ever, QuarkWorks is available to help with any software application project — web, mobile, and more! If you are interested in our services you can check out our website. We would love to answer any questions you have! Just reach out to us on our Twitter, Facebook, LinkedIn, or Instagram.

For monthly updates, subscribe to our general newsletter here.

--

--