What's new in Constraint Layout 1.1.x

Some weeks ago, in a session on Google I/O, we got an announcement of a new release of ConstraintLayout. But, we didn't get so much info about what's inside the package, only a very superficial blog post. No docs, no examples.

So, I searched around a bit, decompiled some classes and did a dive into this release to check what's new, and how them work.

Percent Dimensions

The default behavior of widgets of width 0dp (or match_constraint) is spread (configurable through the layout_constraintWidth_default property). In ConstraintLayout 1.0.x, we had a choice to change it to wrap, and in 1.1.x, we have a new value, percent, that allow us to set a widget to take some percentage of the available space.

<!-- the widget will take 40% of the available space -->
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.4"

Barriers

From this new widget, we have some example from ConstraintLayout.com. Barriers will avoid one or more widgets to bypass the Barrier. When this occurs, the Barrier will move itself, and avoiding the widget(s) to be placed above it.

In the example below, the end property of both text1 and text2 cannot bypass the Barrier. When this occurs, the Barrier will move itself to the right (or to the left, if in a RTL layout). This is particulary handful when dealing with different widget sizes, depending of some configuration or internationalization.

<android.support.constraint.ConstraintLayout...>
  <TextView
android:id=”@+id/text1" ... />
  <TextView
android:id=”@+id/text2" ... />
  <android.support.constraint.Barrier
android:id=”@+id/barrier”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
app:barrierDirection=”end” <!-- start, top, bottom, right... -->
app:constraint_referenced_ids=”text1,text2" />
  <TextView
android:id=”@+id/text3"
...
app:layout_constraintStart_toEndOf=”@+id/barrier” />
</android.support.constraint.ConstraintLayout>

Group

Groups, like the Guidelines, are widgets with size 0. But Group helps to apply some action to a set of widgets. The most common case, is to control a visibility of a collection of widgets. When dealing with this scenario, the most common solution was to maintain yourself a list or set of views inside the Activity or Fragment, or even adding a ViewGroup and put all the views inside of it, controlling the visibility of the container. Now, you only need to add their ids to the Group, and group will propagate the actions to all plugged views.

<android.support.constraint.ConstraintLayout ...>
  <TextView
android:id=”@+id/text1" ... />
  <TextView
android:id=”@+id/text2" ... />
  <android.support.constraint.Group
android:id=”@+id/group”
...
app:constraint_referenced_ids=”text1,text2" />
</android.support.constraint.ConstraintLayout>

In this case, if we call

group.setVisibility(View.GONE);

then text1 and text2 will receive the visibility GONE.

Placeholders

Wow, this one is big. Think about Placeholder like a templating for ConstraintLayout. To show this in a practice way, let's take the example from the I/O talk. We will create 2 different layouts, one for each configuration (default and landscape). But, instead of using the widgets from our layout (ImageViews, TextViews, and so), we will use Placeholders.

<!-- res/layout/template.xml -->
<merge ...>

<android.support.constraint.Placeholder
android:id=”@+id/template_main_image”
...
app:content=”@+id/top_image” />
  <android.support.constraint.Placeholder
android:id=”@+id/templace_action”
...
app:content=”@+id/action_button” />
</merge>

and

<!-- res/layout-land/template.xml -->
<merge ...>

<android.support.constraint.Placeholder
android:id=”@+id/template_main_image”
...
app:content=”@+id/top_image” />
<android.support.constraint.Placeholder
android:id=”@+id/templace_action”
...
app:content=”@+id/action_button” />
</merge>

Then, in the layout itself, that one that we'll be using in our Fragment or Activity, we only add the widgets, without any positioning info. And then we include the template in the layout using the include tag.

// res/layout/activity_my.xml
<android.support.constraint.ConstraintLayout ...>
  <! -- constraints not needed -->
<ImageView
android:id=”@+id/top_image” ... />
  <! — não precisa de constraints -->
<ImageButton
android:id=”@+id/action_button” ... />
  <include
layout=”@layout/template” />
</android.support.constraint.ConstraintLayout>

Other great feature from Placeholder is to change its referenced id in runtime, allowing you to create dynamic layouts (and even cool animations) with considerably less effort than using another ways (like Scenes).

public class MainActivity extends AppCompatActivity {
  private Placeholder placeholder;
private ConstraintLayout root;
  @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}
  public void onClick(View view) {
TransitionManager.beginDelayedTransition(root);
placeholder.setContentId(view.getId());
  }
}

So that's it! At least what I found by myself. If you find someone new that's not present here, or have a link with some official docs, or a wider explanation, please post here in the comments!

Like it and share if this was useful for you :)

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.