Building User Interfaces with ConstraintLayout
We talked about the ConstraintLayout in a previous post and compared it to Auto Layout. Since then, has gone from alpha to beta, and the latest version (beta4) packs further speed improvements and fixes. Furthermore, Android Studio 2.3 (currently canary 2, not yet final) made improvements to the editor.
In this post, we’ll explore some examples.
Example: Centering Views
Auto Layout for iOS and macOS exposes the
centerY anchors. Centering a view in its parent view is as simple as adding a constraint between the view’s and its parent’s center anchors. Similarly, center-aligning multiple views is achieved by creating the constraints between their centers.
ConstraintLayout does not have center anchors, but there are several mechanisms that can achieve the same effect.
The first approach is to create a guideline with the percent constraint set to 0.5:
app:layout_constraintGuide_percent="0.5", and to align the view’s left and right anchors to the guideline:
The second approach is to constrain the left and right anchors of the view to its parent:
ConstraintLayout alpha 9 added the chains feature, which makes it possible to achieve many of the tricks that would previously require a nested LinearLayout.
A “chain” is a set of views that are connected pair-wise by bi-directional constraints. In other words, the simplest chain consists of two views that have constraints against each other in the same dimension, for example:
<Button ... app:layout_constraintRight_toLeftOf="@id/button4" app:layout_constraintHorizontal_chainStyle="packed" .../> <Button ... app:layout_constraintLeft_toRightOf="@+id/button3" .../>
Chains can be “spread,” “packed” or “spread inside”; this is controlled by the
app:layout_constraintHorizontal_chainStyle property (there is also a
Vertical version). Making the chain packed pushes the views close to each other and making it spread allocates the empty space around them.
The first exercise in our Android Programming guide builds a quiz application with a UI that looks like this:
The UI specifications might boil down to something like this:
- It should display the question text view, with margins on the left and the right, 8 points above the horizontal center line.
- It should display two buttons, each 8 points on either side of the vertical center line, 8 points below the horizontal center line.
This is the layout used in the book:
In order to show the buttons side-by-side below text, the book uses two nested
LinearLayouts. It works perfectly well, but in more complex UIs nesting layouts may lead to performance problems that result from some implementation details of the layout process. When a view or a layout is invalidated (i.e., changes content, size, or position), its container, or parent view, is also invalidated. Since this process is recursive, a single change in the view hierarchy may lead to a mass of updates. Thus, in general, it is desirable to keep the view hierarchy as flat as possible.
RelativeLayout enables flattening of the view hierarchy, but as mentioned earlier, its inefficiencies made it unsuitable for use in complex UIs.
The new kid on the block,
ConstraintLayout, is set to make efficient constraint-based layouts a thing on Android. What makes
ConstraintLayout better than
RelativeLayout? Use of the Cassowary algorithm and the constraints (pun intended) placed on how the constraints can be set up.
Here’s the same UI designed using
ConstraintLayout (Layout XML file):
It is a bit hard to see all the constraints, so here they are broken down piece by piece:
- The dotted lines are the vertical and horizontal center guidelines.
- The text view and the two buttons define their position relative to those guidelines.
This layout can also be created without using guidelines. Chains to the rescue!
A view can participate in two separate chains, one in the horizontal and one in the vertical direction. For example, the GeoQuiz UI from our Android book can be created using the ConstraintLayout with two chains, rather than using nested LinearLayouts:
Using StackViews is a common way to simplify the constraints on iOS. For example, to create a form that contains text labels and text fields, you could use a vertical
StackView that contains horizontal
StackViews with the
UITextField. To align the text fields, we would add a leading constraint to all of them.
In our iOS Programming Guide, we build the HomePwner application with the detail screen that looks like this:
There are a few things to keep in mind when trying to replicate this UI using ConstraintLayout. Since the layout params have to be unique per view, we cannot align EditTexts with each other and set them a minimum distance from the corresponding TextViews. One workaround is to introduce a helper Spacer view and define the left/right constraints against it (Layout XML file):
ConstraintLayout has come a long way since its first alpha version. This post explores a few relatively simple user interfaces that can be constructed with its help. However, the real promise of ConstraintLayout will be realized in more complex user interfaces that typically would require several layers of nested layouts, reducing the depth of the view hierarchy and thus improving layout performance.
Would you like to see more examples of ConstraintLayout in action? Let us know in the comments!