preface

In the last article, we took a closer look at ConstraintLayout version 1.0.2. The 1.1.0 version of the article that was promised at that time has not come out until now, a long time ago. ConstraintLayout 1.1.0 is a stable version that Google announced On Thursday, because it was afraid that it would clash with the current version (and it did). So I reorganized and republished this article during the weekend break.

If you do not understand ConstraintLayout and have not read the previous article, it is strongly recommended that you finish this article because it is only a complement to it. If there are omissions or mistakes, welcome to add and correct.

To prepare

implementation 'com. Android. Support. The constraint, the constraint - layout: 1.1.0'
Copy the code

Circular Positioning

Circular Positioning allows one control to set the distance and Angle between it and the center of another control. The properties that can be set are:

  • Layout_constraintCircle: References the ID of another control.
  • Layout_constraintCircleRadius: Distance to another control center.
  • Layout_constraintCircleAngle: The Angle of the control (clockwise, 0-360 degrees).

The following to the head to set a badge as an example, to demonstrate its use:

<? The 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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.github.airsaid.constraintlayoutdemo.MainActivity"> <ImageView android:id="@+id/img_avatar" android:layout_width="60dp" android:layout_height="60dp" android:src="@mipmap/ic_avatar" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/txt_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="VIP" android:textColor="#FFFF00" android:textStyle="bold" app:layout_constraintCircle="@id/img_avatar" app:layout_constraintCircleAngle="45" app:layout_constraintCircleRadius="30dp" /> </android.support.constraint.ConstraintLayout>Copy the code

Running results:

Enforcing constraints

Prior to version 1.1, setting constraints on a control (e.g., minWidth, etc.) did not work if you set the size to WRAP_CONTENT. The effect of a mandatory constraint (Enforcing constraints) is to make the constraint work even if the control is set to WRAP_CONTENT.

The attributes you need to use are:

  • app:constrainedWidth=”true|false”
  • app:constrainedHeight=”true|false”

The following example illustrates the comparison between no and mandatory constraints:

<ImageView
        android:id="@+id/img_avatar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_avatar"
        app:layout_constrainedWidth="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_max="100dp" />

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_avatar"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/img_avatar"
        app:layout_constraintWidth_max="100dp" />
Copy the code

Running results:

Dimensions

In version 1.1, when the control is set to MATCH_CONSTRAINT (0dp), two new decorator properties are added to the set size:

  • Layout_constrainWidth_percent.
  • Layout_constrainHeight_percent.

These properties specify what percentage of the width or height of the current control is the parent control. The value can be set between 0 and 1, with 1 being 100%.

Set the width of the avatar to 80% of the width of the parent control. Example:

<ImageView
    android:id="@+id/img_avatar"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    android:src="@mipmap/ic_avatar"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintWidth_percent="0.8" />
Copy the code

Running results:

Margins and chains

As of version 1.0-Beta4 (known) setting marginRight/End for controls in a chain is not effective (I feel this is a Bug). In stable 1.1, however, both the right and left margins are effective and count. And margins are taken into account when calculating the remaining space.

Optimizer

Remember, ConstraintLayout will have to measure the control twice when we use MATCH_CONSTRAINT, which is expensive.

ConstraintLayout is optimized by the Optimizer. The attribute set to ConstraintLauyout is:

  • Layout_optimizationLevel.

Values that can be set are:

  • None: No optimizations are applied.
  • Standard: Optimizes only direct and barrier constraints (default).
  • Direct: Optimizes direct constraints.
  • Barrier: Optimizes barrier constraints.
  • Chain: Optimization of chain constraints (experiment).
  • Dimensions: Optimized size measurement (experiment).

When setting a value, you can set multiple values, for example:

app:layout_optimizationLevel="direct|barrier|dimensions"
Copy the code

Barrier

When working with a layout, we sometimes encounter situations where the layout changes size depending on the amount of data. Here are some examples:

(Image from official)

As you can see from the figure above, when the size of control A and control B is uncertain, View3 has the wrong constraint object. If A is used as A constraint, then B will be occluded if the width of B is too wide, and the same is true with B as A constraint.

This is where barriers come in handy. Just like GuideLine, it’s a virtual View that isn’t visible to the interface. The purpose is to assist in layout.

The properties available for Barrier are:

  • BarrierDirection: Sets the location where the Barrier is created. The options are bottom, end, left, right, start, and Top.
  • Constraint_referenced_ids: control that sets Barrier references. You can set multiple parameters. The value can be id, ID. (@id/ is not required)
  • BarrierAllowsGoneWidgets: Default to true, meaning that when the control referenced by the Barrier is GONE, the Barrier defaults to create on the parsed location of the GONE control. If set to false, GONE controls are not taken into account.

Instead of looking at the code, let’s see how the Barrier is resolved:

<? The 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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context="com.github.airsaid.constraintlayoutdemo.MainActivity"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Title" android:textSize="16sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="This is a descriptive text." app:layout_constraintStart_toStartOf="parent"  app:layout_constraintTop_toBottomOf="@id/title" /> <android.support.constraint.Barrier android:id="@+id/barrier" android:layout_width="match_parent" android:layout_height="match_parent" app:barrierDirection="end" app:constraint_referenced_ids="title, desc" /> <TextView android:id="@+id/content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:text="This is a piece of content that is very long and long very long and long ..." app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/barrier" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>Copy the code

Running results:

Another case:

Perfect solution.

Group

A Group controls the visibility of a set of controls. The available attributes are:

  • Constraint_referenced_ids: Specifies the ID of the referenced control.

Ex. :

<android.support.constraint.Group
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="gone"
    app:constraint_referenced_ids="title, desc" />
Copy the code

If there are multiple groups, it is possible to specify the same control at the same time, ultimately using the Group declared last in the XML.

Placeholder

Placeholder is a Placeholder, which is a Placeholder, as its name suggests.

When placed in the Placeholder, placeholders can be turned into valid views using the setContentId() method. If the view already exists on the screen, it will disappear from its original position.

In addition, you can use the setEmptyVisibility() method to set the visibility of placeholders when the view does not exist.

The following example demonstrates the use of placeholders. When the top avatar is clicked, the top avatar disappears and appears in the placeholder:

<? The 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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context="com.github.airsaid.constraintlayoutdemo.MainActivity"> <ImageView android:id="@+id/avatar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_avatar" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <android.support.constraint.Placeholder android:id="@+id/placeholder" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>Copy the code

Running results:

conclusion

As you can see from this article, ConstraintLayout is getting stronger, better, and has introduced optimizers to make it even better. So why not ConstraintLayout? !