ConstraintLayout

ConstraintLayout

Article Directory

Introduction

Constraint Layout ConstraintLayout is a ViewGroup, which can be used in Android systems above Api9. Its appearance is mainly to solve the problem of excessive layout nesting, and to position and adjust widgets in a flexible way. Starting from Android Studio 2.3, the official template uses ConstraintLayout by default

ConstraintLayout official document

Why use ConstraintLayout

In the development process, we often encounter some complex UIs, and there may be too many layout nesting problems. The more nesting, the more time and computing power required for the device to draw the view, for example:

suppose now To write such a layout, someone might write it like this:
1. it is a vertical LinearLayout with two horizontal LinearLayouts, and then a TextView in the horizontal LinearLayout. This way of writing is nested in two layers of LinearLayout

Some people consider the risks of nested layouts, so use a RelativeLayout to hold all the controls. Since RelativeLayout can solve the problem, why use ConstraintLayout? Because ConstraintLayout is more flexible to use than RelativeLayout and has better performance! Another point is that ConstraintLayout can constrain the position and size of the control according to the proportions, which can better adapt to models with different screen sizes.

Add dependency

Use androidx here

implementation 'androidx.constraintlayout: constraintlayout: 1.1.3' Copy Code

how to use

Location

The attributes that determine the location provide the following 13 attributes

  • layout_constraintLeft_toLeftOf//align the left side of the desired view with the left side of another view
  • layout_constraintLeft_toRightOf
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintBaseline_toBaselineOf
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

chestnut

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView1"/> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView2" app:layout_constraintLeft_toRightOf="@+id/tv1"/> <TextView android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView3" app:layout_constraintTop_toBottomOf="@+id/tv1"/> </androidx.constraintlayout.widget.ConstraintLayout> Copy code

For the boundary of a View, the official gave the following picture: In

general, just use layout_constraintLeft_toRightOf:

As shown in the figure, the heights of the two TextViews are inconsistent, but they want their text to be aligned. At this time, you can use layout_constraintBaseline_toBaselineOf

<TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#D8BFD8"/> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="20dp" android:text="TextView2" android:background="#DDA0DD" app:layout_constraintLeft_toRightOf="@+id/tv1" app:layout_constraintBaseline_toBaselineOf="@+id/tv1" /> Copy code

Angle positioning

Angular positioning means that an angle and a distance can be used to constrain the centers of two spaces

The TextView2 in the above example uses the following 3 attributes:

app:layout_constraintCircle="@+id/tv1" app:layout_constraintCircleAngle="120" (angle) app:layout_constraintCircleRadius="150dp" (distance) Copy code


The center of TextView2 is 120 degrees from the center of TextView1, and the distance is 150dp

Margin

Commonly used margin

The common attributes of ConstraintLayout's margins are as follows:

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

It seems that there is no difference with other layouts, but in fact, to realize the margin of the control in ConstraintLayout, you must first constrain the position of the control in ConstraintLayout

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#D8BFD8" android:layout_marginLeft="10dp" android:layout_marginTop="10dp"/> </androidx.constraintlayout.widget.ConstraintLayout> Copy code


If in other layouts, the position of TextView1 should be a 10dp margin from the left and above the border, but in ConstraintLayout, it does not take effect because there is no constraint on the position of TextView1 in the layout. The correct wording is as follows:

<TextView android:id="@+id/tv1" ...... android:layout_marginLeft="10dp" android:layout_marginTop="10dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/> Copy code

Constrain the left and upper edges of TextView1 to the left and upper edges of the parent, so that the margin will take effect, and the effect is as follows:

Pay attention to two points when using the margin:

  1. Controls must constrain a relative position in the layout
  2. margin can only be greater than or equal to 0

goneMargin

goneMargin is mainly used for the margin value used when the visibility of the constrained control is set to gone. The properties are as follows:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

Chestnut:
The left side of TextView2 is constrained to the right side of TextView1, and an app:layout_goneMarginLeft= 10dp is set for TextView2, the code:

<TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#D8BFD8"/> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView2" android:gravity="center" android:background="#D8BFD8" app:layout_constraintLeft_toRightOf="@+id/tv1" app:layout_goneMarginLeft="10dp"/> Copy code

The effect is shown in the figure, TextView2 is on the right side of TextView1, and there is no margin. At

this time, the visibility of TextView1 is set to gone, and the effect is as follows: After

TextView1 disappears, TextView2 has a margin of 10dp from the left.

Centering and offset

In RelativeLayout, the way to put the control in the middle of the layout is to set layout_centerInParent to true, and the way to write in ConstraintLayout is:

app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" Copy code

It means to constrain the top, bottom, left, and right of the control to the top, bottom, left, and right of the layout, so that the control can be placed in the middle of the layout

Similarly, the horizontally centered layout_centerHorizontal in RelativeLayout is equivalent to the left and right sides of the ConstraintLayout constraint control for the left and right sides of the parent; the vertical centered layout_centerVertical in the RelativeLayout is equivalent to the upper and lower sides of the ConstraintLayout constraint control for the parent.

When centering does not take effect

The width and height of ConstraintLayout should be set to match_parent, otherwise the centering will not take effect

android:layout_width="match_parent" android:layout_height="match_parent" Copy code

In addition to margin, ConstraintLayout also provides another offset attribute:

  • layout_constraintHorizontal_bias horizontal offset
  • layout_constraintVertical_bias vertical offset

If you want to realize the horizontal offset now, assign a value in the range of 0-1 to the layout_constraintHorizontal_bias of TextView1. If the value is 0, then TextView1 is on the leftmost side of the layout. If the value is 1, TextView1 is on the rightmost side of the layout. If the value of 0.5 is assigned, it will be centered horizontally, if the value of 0.3 is assigned, it will be more inclined to the left side. The
same is true for the vertical offset

<androidx.constraintlayout.widget.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"> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#D8BFD8" app:layout_constraintHorizontal_bias="0.3" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> Copy code

Size constraints

The size of the control can be specified in four different ways:

  1. Use specified size
  2. Use wrap_content to let the control calculate its own size.
    When the height or width of the control is wrap_content, you can use the following attributes to control the maximum and minimum height or width:
    android:minWidth minimum width
    android:minHeight minimum height
    android:maxWidth maximum width
    android:maxHeight The maximum height
    Attention! When ConstraintLayout is version 1.1 or less, you need to add mandatory constraints to use these properties, as shown below:
    app:constrainedWidth= true
    app:constrainedHeight= true
  3. Using 0dp (MATCH_CONSTRAINT) is
    officially not recommended to use match_parent in ConstraintLayout, you can set 0dp (MATCH_CONSTRAINT) to match constraints instead of match_parent
<TextView android:id="@+id/tv1" android:layout_width="0dp" android:layout_height="wrap_content" android:text="TextView1" android:gravity="center" android:background="#D8BFD8" android:layout_marginLeft="50dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> Copy code

The width is set to 0dp, the left and right sides of the parent are constrained, and the left margin is set to 50dp, the effect is as follows:

  1. Aspect ratio
    When at least one dimension of width or height is set to 0dp, the aspect ratio can be set through the attribute layout_constraintDimensionRatio
<TextView android:id="@+id/tv1" android:layout_width="0dp" android:layout_height="100dp" android:text="TextView1" android:gravity="center" android:background="#D8BFD8" app:layout_constraintDimensionRatio="1:1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> Copy code

The width is set to 0dp and the aspect ratio is set to 1:1. At this time, TextView1 is a square, and the effect is as follows:

In addition, when setting the value of the aspect ratio, you can also add W or H in front to specify them respectively Width or height restrictions. For example:
app:layout_constraintDimensionRatio="H,2:3" refers to height:width=2:3
app:layout_constraintDimensionRatio="W,2:3" refers to width:height=2:3

chain

If two or more controls are constrained together as shown in the figure below, they can be considered as a chain (the figure shows a horizontal chain, the same is true for vertical)


chestnut:

<TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#DDA0DD" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv2" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView2" android:gravity="center" android:background="#D8BFD8" app:layout_constraintLeft_toRightOf="@+id/tv1" app:layout_constraintRight_toLeftOf="@+id/tv3" /> <TextView android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView3" android:gravity="center" android:background="#FFC0CB" app:layout_constraintLeft_toRightOf="@+id/tv2" app:layout_constraintRight_toRightOf="parent" /> Copy code

The three TextViews are mutually constrained, and the two TextViews at both ends are respectively constrained with the parent to become a chain. The effect is as follows:

the first control of a chain is the chain head of this chain, we can set layout_constraintHorizontal_chainStyle in the chain head to change the whole chain The style of the chain. Chains provides 3 styles, namely:

  • CHAIN_SPREAD expand element (default);
  • CHAIN_SPREAD_INSIDE expand the element, but the two ends of the chain are close to the parent;
  • CHAIN_PACKED The elements of the chain will be packed together. The

    above example creates a style chain. In addition to the style chain, you can also create a weight chain.
    You can notice that the widths of the three TextViews used above are all wrap_content. If we put the widths Set to 0dp. At this time, you can set the horizontal weight layout_constraintHorizontal_weight in each TextView (constraintVertical is vertical) to create a weight chain
<TextView android:id="@+id/tv1" android:layout_width="0dp" ...... app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tv2" app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_weight="1" /> <TextView android:id="@+id/tv2" android:layout_width="0dp" ...... app:layout_constraintLeft_toRightOf="@+id/tv1" app:layout_constraintRight_toLeftOf="@+id/tv3" app:layout_constraintHorizontal_weight="2" /> <TextView android:id="@+id/tv3" android:layout_width="0dp" ...... app:layout_constraintLeft_toRightOf="@+id/tv2" app:layout_constraintRight_toRightOf="parent" app:layout_constraintHorizontal_weight="3" /> Copy code

Auxiliary tools

In addition to the properties of ConstraintLayout itself, Google also provides a lot of auxiliary layouts (just play an auxiliary role in the layout, and will not be displayed in the interface) to make the function of ConstraintLayout more powerful. Below, let s take a look at these layouts one by one

Guideline

Guildline is like an auxiliary line. It helps you complete the layout when previewing (not displayed on the interface). The positioning principle of ConstraintLayout is that a View refers to the relative layout of other Views. If sometimes the current layout does not have a suitable reference View, and It would be too heavy to build a View dedicated to positioning. This situation is where GuideLine comes in.

The main attributes of Guildline:

  • android:orientation vertical, horizontal horizontal
  • layout_constraintGuide_begin start position
  • layout_constraintGuide_end end position
  • layout_constraintGuide_percent The percentage from the top (orientation = horizontal, the distance from the left)
<androidx.constraintlayout.widget.Guideline android:id="@+id/guideline1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_begin="50dp"/> <androidx.constraintlayout.widget.Guideline android:id="@+id/guideline2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.5"/> Copy code

Guideline1 is the horizontal auxiliary line, the starting position is 50dp from the top, the guideline is 2 vertical auxiliary lines, and the starting position is 0.5 of the screen width (midpoint position)

Group

Group can group multiple controls into a group, which is convenient to hide or display a group of controls.
For example, we use the three TextViews in the chain section as an example.

<androidx.constraintlayout.widget.Group android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="tv1,tv3" android:visibility="invisible"/> Copy code

Now there are 3 TextViews side by side, use Group to group TextView1 and TextView3 into one group, and then set the visibility of this group of controls

Placeholder

Placeholder refers to a placeholder. In Placeholder, you can use setContent() to set the id of another control to move this control to the placeholder position

<androidx.constraintlayout.widget.Placeholder android:layout_width="wrap_content" android:layout_height="wrap_content" app:content="@+id/tv1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#DDA0DD" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> Copy code

Create a new Placeholder constraint on the upper left corner of the screen, create a new TextView constraint on the upper right corner of the screen, set app:content="@+id/tv1" in the Placeholder, then the TextView will run to the upper left corner of the screen

Placeholder itself does not draw any content, but you can draw the content of the id View to its own position by setting app:content="id", and the original id View is just like gone in the same

application scenario, for example, it can be used as a position Template, only need to write content view after introduction; use code to dynamically change content, combined with TransitionManager can do some interesting transition animations, etc.

Barrier

Barrier, a virtual View. The main solution is to solve the following problems:

Suppose there are three controls ABC, the width of AB is not fixed, and C is on the right of AB. At this time, whether C is constrained to the right of A or B, it is wrong. When this happens, you can use Barrier to solve it. Barrier can build a barrier on one side of multiple controls. At

this time, C only needs to be constrained to the right side of the Barrier.

<TextView android:id="@+id/tv1" android:layout_width="100dp" android:layout_height="40dp" android:text="TextView1" android:gravity="center" android:background="#DDA0DD" /> <TextView android:id="@+id/tv2" android:layout_width="200dp" android:layout_height="40dp" android:text="TextView2" android:gravity="center" android:background="#D8BFD8" app:layout_constraintTop_toBottomOf="@+id/tv1" /> <androidx.constraintlayout.widget.Barrier android:id="@+id/barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="right" app:constraint_referenced_ids="tv1,tv2"/> <TextView android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="50dp" android:text="TextView3" android:gravity="center" android:background="#FFC0CB" app:layout_constraintLeft_toRightOf="@+id/barrier" /> Copy code

app:constraint_referenced_ids is the control referenced by the barrier, which can be set multiple (separated by ",")

app:barrierDirection is the position of the barrier, the values that can be set are: bottom, end, left, right, start, top

ConstraintSet use, dynamically modify the constraint layout

Official document

In the past, when we dynamically modify the size and position of the controls in the layout and the relative relationship with other controls in the code, we need to use

LayoutParams
, Different layouts have corresponding different
LayoutParams
The sub-category is very cumbersome to use. In the era of ConstraintLayout, it is matched with
ConstraintSet

1. Create and initialize ConstraintSet

ConstraintSet constraintSet = new ConstraintSet(); //Usage 1: Get the constraint set from the ConstraintLayout instance, the most common usage constraintSet.clone(mainLayout) //mainLayout is ConstraintLayout //Usage 2: Get the constraint set from the layout constraintSet.clone (context, R.layout.my_layout) //The root layout of my_layout.xml must be ConstraintLayout //Usage 3: Obtain the constraint set from other constraint sets constraintSet.clone(otherConstraintSet) Copy code

2. Set constraints between components

constraintSet.connect(startID: Int, startSide: Int, endID: Int, endSide: Int, margin: Int) constraintSet.connect(startID: Int, startSide: Int, endID: Int, endSide: Int) Copy code

3. You can modify the size of the control

constrainWidth( int viewId, int width) constrainHeight( int viewId, int height) constrainPercentWidth( int viewId, float percent) constrainPercentHeight ( int viewId, a float Percent) copying the code

Other APIs related to size include:

constrainDefaultWidth/constrainDefaultHeight
constrainMaxWidth/constrainMaxHeight
constrainMinWidth/constrainMinHeight is
used to set some default, maximum and minimum sizes, not commonly used, you can see the example shown in the following article RecyclerView to set the maximum height

4. Set up the animation

TransitionManager.beginDelayedTransition(mainLayout) Copy code

5. Apply once to make the settings take effect

constraintSet.applyTo(rootLayout) Copy code

Give a pear

Button operate = findViewById(R.id.operate); ConstraintLayout constraintLayout = findViewById(R.id.view_constraintLayout); ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(constraintLayout); operate.setOnClickListener(v -> { constraintSet.connect(R.id.button2,ConstraintSet.TOP,R.id.button1,ConstraintSet.BOTTOM,dpToPx( this , 40 )); constraintSet.connect(R.id.button2,ConstraintSet.LEFT, ConstraintSet.PARENT_ID,ConstraintSet.LEFT); constraintSet.constrainWidth(R.id.button2, ConstraintSet.WRAP_CONTENT); constraintSet.constrainHeight(R.id.button2, dpToPx( this , 100 )); TransitionManager.beginDelayedTransition(constraintLayout); constraintSet.applyTo(constraintLayout); }); Copy code


This is just the most basic usage of ConstraintSet. For more usage, please refer to the link at the end of the article.

ConstraintLayout Usage Full Analysis
Constraint Layout ConstraintLayout Read this article is enough/