Exploring the new Android ConstraintLayout

Last week at Google I/O we saw the introduction of loads of great Android related news. Whilst I’d love to sit here and talk about everything that was announced, we’re going to take a quick look at the new and exciting ConstraintLayout for Android.


To get a better understanding of the ConstraintLayout I took an existing project of mine (Bourbon) and manually converted the layouts to use the new ConstraintLayout. Feel free to check it out on github!


Setting up

Before we get started, there’s a few things you’ll need to do if you want to try out the new ConstraintLayout.

compile 
'com.android.support.constraint:constraint-layout:1.0.0-alpha1'

And that’s it, you should now be all ready to go!

So, what is the ConstraintLayout?

The ConstraintLayout is a powerful new class, imagine a RelativeLayout on steroids - yea, that’s the ConstraintLayout. It allows us to lay out child views using ‘constraints’ to define position based relationships between different views found in our layout.

The aim of the ConstraintLayout is to help reduce the number of nested views, which will improve the performance of our layout files. The layout class also makes it easier for us to define layouts than when using a RelativeLayout as we can now anchor any side of a view with any side of another, rather than having to place a whole view to any side of another.

For example, the attributes of a relative layout allow us to position a view using:

  • layout_toRightOf
  • layout_toLeftOf
  • layout_toTopOf
  • layout_toBottomOf

However, the ConstraintLayout features several more attributes:

  • layout_constraintTop_toTopOf — Align the top of the desired view to the top of another.
  • layout_constraintTop_toBottomOf — Align the top of the desired view to the bottom of another.
  • layout_constraintBottom_toTopOf — Align the bottom of the desired view to the top of another.
  • layout_constraintBottom_toBottomOf — Align the bottom of the desired view to the bottom of another.
  • layout_constraintLeft_toTopOf — Align the left of the desired view to the top of another.
  • layout_constraintLeft_toBottomOf — Align the left of the desired view to the bottom of another.
  • layout_constraintLeft_toLeftOf — Align the left of the desired view to the left of another.
  • layout_constraintLeft_toRightOf — Align the left of the desired view to the right of another.
  • layout_constraintRight_toTopOf — Align the right of the desired view to the top of another.
  • layout_constraintRight_toBottomOf — Align the right of the desired view to the bottom of another.
  • layout_constraintRight_toLeftOf — Align the right of the desired view to the left of another.
  • layout_constraintRight_toRightOf — Align the right of the desired view to the right of another.
  • If desired, attributes supporting start and end are also available in place of left and right alignment.

Phew, that’s a lot of attributes, right? These all give us a great amount of control over the positioning of our views within the ConstraintLayout, much more so than that of the RelativeLayout.

Note: The ConstraintLayout is also compatible right down to API level 9 🐵

Constraint handles

A Constraint is essentially a defined rule for a view which declares it’s positioning and alignment on screen, the ConstraintLayout class supports several different types of handles.

Resize Handle

We can change the size of the chosen view by using the resize handle in the layout editor, this re-sizes the view and sets constraints for the new size.

Resizing a view using the resize anchor within the layout editor will automatically re-calculate the constraints that have been previously set on that view.

Side Constraint Handle

The side constraint handle can be used to specify the location of the view within the layout. For example, these anchors can be used to define that the selected view is always displayed to the left of another view, by a specified margin dp value.

This can be set in the layout editor by dragging an anchor point of one view to a side of another view:

Or by setting the desired view attribute in the XML layout:

app:layout_constraintRight_toRightOf="@+id/text_like_count"

Baseline Constraint Handle

The baseline constrain allows use to align the baseline of multiple textviews, regardless of their text sizes.

This can be set in the layout editor by dragging the baseline anchor of the desired TextView to the baseline of another TextView:

Or by setting the desired view attribute in the XML layout:

app:layout_constraintBaseline_toBaselineOf="@+id/text_title"

Note: Baseline contain handles can only be constrained to another baseline.

Vertical Bias

This allows us to position a view along the vertical axis using a bias value, this will be relative to it’s constrained position.

We can set this using the slider in the layout editor (seen below) or using the attribute in our XML like so:

app:layout_constraintVertical_bias="0.5"

Horizontal Bias

This allows us to position a view along the horizontal axis using a bias value, this will be relative to it’s constrained position.

We can set this using the slider in the layout editor (seen below) or using the attribute in our XML like so:

app:layout_constraintHorizontal_bias="0.5"

View Sizing

Within the properties section of the layout editor, you’ll notice a section which states the actual size constraints for the selected view.

Any Size

Inside of the square you can see there, those squiggly lines actually represent how the view will resize in the layout. The lines above state that the views size will obey constraints, meaning it will match_parent and use the available space.

Wrap Content

These lines now state that the views height and width will wrap the content of the view, meaning it will only be as big as it needs to be.

Fixed Size

Finally, these lines state that the views height and width are of a fixed size, which is declared in dp.

Auto-connect

Auto-connect allows you to place a view inside the layout editor and have it automatically calculate and set the constraints for you - how handy is that!

To use Auto-Connect:

Manual Constraints

It’s possible to disable auto-connect if you wish to manually set the constraints within the layout editor. Personally, this gives you much more control over the constraints and saves you time deleting the constraints you don’t need that were automatically set.

To use manual constraints you need to disable auto-connect:

Inference

Similar to the behaviour of AutoConnect, Inference can be used to automatically (and magically…) create constraints between multiple views within your layout for you. The difference from AutoConnect is that inference calculates and sets constraints for all of the views in your layout file, rather than just the selected view.

Deleting Constraints

Within the layout editor you can easily remove constraints from a view. This can be done in one of two ways.

Single Constraints

You can remove a single constraint by simply clicking on the anchor point of the constraint that you wish to delete.

All Constraints

When a view is selected, a little icon will appear to the bottom left hand side - clicking this icon will remove all of the constraints that have been set on that view.

Example

Let’s take a little look at a layout from my Constraints sample project. The layout for a Dribbble Shot item is displayed within the layout editor as below:

You can see the constraints that have been defined, these are:

  • The Image displayed at the top of the view has constraints which align it to the top, left, right and bottom of its parent container. This has the effect of centring the view in it’s parent container.
app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout” app:layout_constraintEnd_toEndOf=”@+id/constraintLayout” app:layout_constraintStart_toStartOf=”@+id/constraintLayout” app:layout_constraintTop_toTopOf=”@+id/constraintLayout”
  • The ‘Japan’ text view is aligned to the left and bottom of its container, whilst also being aligned to the left of the heart image - this is to ensure that they don’t overlap.
app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout” app:layout_constraintEnd_toStartOf=”@+id/imageView” app:layout_constraintStart_toStartOf=”@+id/constraintLayout”
  • The heart count TextView is aligned to the right and bottom of it’s container, essentially on the opposite side of the ‘Japan’ TextView.
app:layout_constraintBottom_toBottomOf=”@+id/constraintLayout” app:layout_constraintEnd_toEndOf=”@+id/constraintLayout”
  • Finally, the heart image is aligned to the top / bottom of the heart count TextView and the right side of the heart ImageView is aligned with the left side of the heart count TextView.
app:layout_constraintBottom_toBottomOf=”@+id/text_like_count” app:layout_constraintEnd_toStartOf=”@+id/text_like_count” app:layout_constraintTop_toTopOf=”@+id/text_like_count”

Within a layout file, this views with their constraints look like so:

From this simple example we can see the possibilities that the ConstraintLayout provides. You can check out more of the layouts using constraints in the Browse Fragment Layout, Shot Fragment Layout, Comment Item Layout and the Shot Item Layout.

Why not try re-implementing some of your existing layouts using the ConstraintLayout?

And that’s it!

In this article we’ve taken a quick look at the new ConstraintLayout, it’s capabilities and how we can use it to create more efficient layouts within our applications. Remember, the layout is still in alpha and I’m not confident that it’s ready to use in production yet - but do be sure to experiment with it for when it is ready to be used out in the wild! This has only been a brief post, so please be sure to get setup and try this out for yourself :)

I’d love to see if / where you’re using the ConstraintLayout, so please drop me a tweet or leave a response if you have anything to share (or even any questions to ask!)

Check out my other projects at hitherejoe.com