The following is the first few sections of a chapter from The Busy Coder's Guide to Android Development, plus headings for the remaining major sections, to give you an idea about the content of the chapter.


Advanced ConstraintLayout

The original chapter on ConstraintLayout covered some basic uses of this container class, particularly how it can be used in the place of classic containers like LinearLayout and RelativeLayout. In this chapter, we will explore other features that ConstraintLayout offers and other use cases for this container.

This chapter examines some more layouts from the Containers/Sampler sample project.

Prerequisites

Understanding this chapter requires that you have read the core chapters of this book, particularly the original chapter on ConstraintLayout.

Disclosing Your Bias

For a given axis, there are roughly three models for how you use constraints for a given widget:

In the first case, the widget is simply attached to the anchor point, taking any margins into account. In the second case, the widget is stretched between the two anchor points.

The default for the third case is for the widget to be centered within the available space between the two anchor points, assuming that its size on that axis is smaller than the available space. However, we can use “bias” to slide the widget along that axis away from the center point, so it appears closer to one end than the other.

Centering a widget within a RelativeLayout is a matter of using android:layout_centerInParent="true":

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:text="@string/button"/>

</RelativeLayout>

Centering a widget within a ConstraintLayout is more verbose, requiring you to anchor all four sides of the widget to the four edges of the ConstraintLayout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

However, that verbosity also allows us to apply biases, via app:layout_constraintHorizontal_bias and app:layout_constraintVertical_bias:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.33"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.32999998"
    tools:layout_editor_absoluteX="98dp" />

</android.support.constraint.ConstraintLayout>

The default values for the biases are 0.5, meaning that the center point of the widget is centered evenly between the two anchor points. A bias of less than 0.5 slides the widget towards the beginning of that axis (towards the start size of the horizontal axis or the top of the vertical axis). A bias of higher than 0.5 slides the widget towards the end of that axis.

So, for bias values of 0.33 along each axis, the Button is slid towards the start and top:

Bias Sample, Using ConstraintLayout
Figure 445: Bias Sample, Using ConstraintLayout

It is impractical to replicate this using the classic container classes. LinearLayout comes closest, using something like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
  android:weightSum="100">

  <View
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="33" />

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="67"
    android:orientation="horizontal"
    android:weightSum="100">

    <View
      android:layout_width="0dp"
      android:layout_height="match_parent"
      android:layout_weight="33" />

    <Button
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="@string/button" />
  </LinearLayout>

</LinearLayout>

Here, we use empty View widgets as spacers, along with weights to get the proportions the way that we want. However, this puts a corner of the Button at the appropriate location, not its center. So, compared to the ConstraintLayout approach, the LinearLayout implementation is a bit closer to the center:

Bias Sample, Using LinearLayout
Figure 446: Bias Sample, Using LinearLayout

ConstraintLayout biases are not limited to constraints placed against the ConstraintLayout edges. You can apply biases based on constraints tied to guidelines or other widgets as well:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <Button
    android:id="@+id/button3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/button"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="@+id/guideline"
    app:layout_constraintHorizontal_bias="0.1"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="@+id/guideline"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.25" />

  <android.support.constraint.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent=".50" />

  <Button
    android:id="@+id/button2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/btn_other"
    app:layout_constraintHorizontal_bias="0.8"
    app:layout_constraintLeft_toRightOf="@+id/button3"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="@+id/button3" />

</android.support.constraint.ConstraintLayout>

Here we have a ConstraintLayout with two buttons. The “Button!” button has two biases:

The “Other Button!” button has a horizontal bias to place it at the 80% mark between the edge of the first button and the screen edge.

The buttons are positioned with those biases applied:

Biases with Widgets, Guidelines, and Edges
Figure 447: Biases with Widgets, Guidelines, and Edges

The configuration tool atop the Attributes pane lets you control the bias, by adjusting the slider for the bias to apply to that particular axis:

Configuration Thingy, Showing 33% Bias
Figure 448: Configuration Thingy, Showing 33% Bias

Centering Yourself

The preview of this section was fed to a gremlin, after midnight.

Keeping Things Proportional

The preview of this section left for Hollywood to appear in a reality TV show.

Constraining the ConstraintLayout Size

The preview of this section was eaten by a grue.

Chains, Without the Whips

The preview of this section is out seeking fame and fortune as the Dread Pirate Roberts.

What If We’re GONE?

The preview of this section is presently indisposed.