ConstraintLayout fully parsed Come and optimize your layout

This article has been originally published on my public account hongyangAndroid.
Please indicate the source for reprinting:
http://blog.csdn.net/lmj623565791/article/details/78011599
This article is from Zhang Hongyang's blog

This article has been originally published on my public account hongyangAndroid, a collection of articles .

I. Overview

ConstraintLayout has been around for a while, but I haven't paid much attention to it, and I have read some text introductions more or less. Most of them are about using visual layout drag and drop. Personally, I haven't been optimistic about drag and drop until I saw this article some time ago:

I introduced the performance advantages of ConstraintLayout in great detail, so I started to learn about ConstraintLayout.

The focus of this article is not on learning the visual interface, but on how to handwrite various constraint layout properties. Recommended for visual interface learning:

Now let’s get to the point. As we all know, when the layout is deeply nested, it is often accompanied by some performance problems. So many times we recommend using RelativeLayout or GridLayout to simplify the depth of the layout.

For simplifying the layout depth, ConstraintLayout can almost achieve the ultimate. Next, we will introduce all common attributes step by step as much as possible through examples.

First we need to introduce our ConstraintLayout and add it to build.gradle:

compile 'com.android.support.constraint:constraint-layout:1.0.2'

Second, to write a Feed Item

Let's first look at a common feed item in a simple news list.

Seeing such a layout, you should use RelativeLayout to do conditional reflection. Of course, in this case, we use ConstraintLayout to write:

<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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#11ff0000"
    tools:context="com.zhy.constrantlayout_learn.MainActivity">


    <TextView
        android:id="@+id/tv1"
        android:layout_width="140dp"
        android:layout_height="86dp"
        android:layout_marginLeft="12dp"
        android:layout_marginTop="12dp"
        android:background="#fd3"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="12dp"
        android:text="马云:一年交税170多亿马云:一年交税170多亿马云:一年交税170多亿"
        android:textColor="#000000"
        android:textSize="16dp"
        app:layout_constraintLeft_toRightOf="@id/tv1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@id/tv1" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="12dp"
        android:text="8分钟前"
        android:textColor="#333"
        android:textSize="12dp"
        app:layout_constraintLeft_toRightOf="@id/tv1"
        app:layout_constraintBottom_toBottomOf="@id/tv1" />

</android.support.constraint.ConstraintLayout>

Looking at the layout above, we seem to see several properties of the pattern:

The first is tv1, which has two unseen properties:

  • app:layout_constraintLeft_toLeftOf="parent"

Literally, it refers to aligning the left side of the control with the parent layout. This property can be used when we want control A to be aligned with the left side of control B.

app:layout_constraintLeft_toLeftOf="@id/viewB"

There is also a similar property that is:

  • app:layout_constraintLeft_toRightOf

It is well understood that the left side of the current property is on the right side. When we want control A to be on the right side of control B, we can set:

app:layout_constraintLeft_toRightOf="@id/viewB"

There are several similar properties:

  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintBaseline_toBaselineOf

An analogy will do.

Now look at the layout just now:

tv1设置了:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"

tv2设置了:

app:layout_constraintLeft_toRightOf="@id/tv1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv1"

tv3设置了:

app:layout_constraintLeft_toRightOf="@id/tv1"
app:layout_constraintBottom_toBottomOf="@id/tv1"

According to our understanding just now, read it again:

tv1 should be in the upper left corner of the parent layout;

tv2 is on the right side of tv1, the right side of tv2 is aligned with the parent layout, and the top of tv2 and tv1 is aligned;

tv3 is to the right of tv1, and tv3 and tv1 are aligned at the bottom.

At this point, you can see that we can now control the relative position of any control to other controls, as well as the relative position to the parent.

Differences from RL

Do you think it looks very similar to RelativeLayout at present?

In fact, there are still obvious differences, let's take a look at an example:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <Button
        android:id="@+id/id_btn01"
        android:layout_width="100dp"
        android:text="Btn01"
        android:layout_height="wrap_content" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/id_btn01"
        android:text="Btn02"
        android:layout_alignParentRight="true"
        />

</RelativeLayout>

Then after what we just learned, put:

layout_toRightOf="@id/id_btn01"layout_alignParentRight="true"

Replace with:

app:layout_constraintLeft_toRightOf="@id/id_btn01"app:layout_constraintRight_toRightOf="parent"

Do you think it's so easy, but let's take a look at the renderings:

Is there a certain difference from what is expected? If you set the width of Btn02 to be very large, you will find even more weird things:

You will find Btn02, like crazy, we set it to the right of btn01, and the alignment to the right of parent is completely invalid! ! !

Don't be afraid, let's you realize why this control is called "Constraint" Layout.

When the control has its own set width, such as warp_contenta fixed value, we add a constraint "Constraint" to the control. This constraint is a bit like a rubber band that will pull the control, but it will not change the size of the control (RL is very Obviously not so).

For example, in the above example, when the width of btn02 is small, we set a constraint on its left side (the right side of btn01) and a constraint on the right side (the right side of parent), when the two constraints take effect at the same time (you It can be considered that both sides are the same one pulling force), btn02 will be centered.

When btn02 is particularly large, it is still these two forces, so what will happen? will cause the left and right sides to exceed the same distance.

So now you must have some questions:

  • How can it be the same as the RL above, the width just occupies the remaining distance (the distance from the right side of btn01 to the right side of the screen)?

This question is a very good question. All the attempts we have just done are performed when the control itself has a specific width; then if you want the width of the control to be controlled according to the constraints, you might as well remove this specific width, that is, set it to 0 try?

right! When we set the width of btn02 to 0, everything is perfect again.

So here, you may ask what the 0 value means. In fact, in ConstraintLayout, 0 represents: MATCH_CONSTRAINT, when you see this constant, do you feel a little easier to understand instantly?

  • Last question, where MATCH_PARENTdid it go?

See the explanation on the official website:

Important: MATCH_PARENT is not supported for widgets contained in a ConstraintLayout, though similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to “parent”.`

So you can think: MATCH_PARENTthis value is no longer supported in ConstraintLayout, you can MATCH_CONSTRAINTachieve a similar effect by matching constraints.

Well, here, we have seen that it has been on par with RelativeLayout, and then let's take a look at the features that RL can't do.

3. Add a banner

We now add a banner at the top of this feed item, with a width of occupying the entire screen and an aspect ratio of 16:6.

It's embarrassing here. In the previous practice, it was difficult to set the aspect ratio in the layout. Generally, we need to operate it in the code, so if you use ConstraintLayout, it supports it.

Take a look at how to support:

<android.support.constraint.ConstraintLayout 
    ...
    tools:context="com.zhy.constrantlayout_learn.MainActivity">

    <TextView
        android:id="@+id/banner"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#765"
        android:gravity="center"
        android:text="Banner"
        app:layout_constraintDimensionRatio="H,16:6"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />


    <TextView
        android:id="@+id/tv1"
        app:layout_constraintTop_toBottomOf="@id/banner"
        ></TextView>
     ...
</...>

We added a banner, remember what we said just now, don't use match_parentit, but set match_contraintit, which is 0, and let the constraints control the width and height of the layout.

So we set both width and height match_contraint, and then these two properties:

app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

To make our width fill the entire parent layout, add a:

app:layout_constraintDimensionRatio="16:6"

This property refers to the aspect ratio, so 16:6 will do what we need.

Well, look at the renderings:

This aspect ratio attribute also supports the following writing:

app:layout_constraintDimensionRatio="W,16:6"
app:layout_constraintDimensionRatio="H,16:6"

You can test it yourself.

Well, here, we have added another attribute, which is still a very useful attribute.

So, let's go ahead and look at another familiar feature.

Fourth, add a few Tabs

Now we want to add 3 tabs at the bottom and divide them equally. Did you think of LinearLayout and weight.

That's right! ConstraintLayout also supports similar properties.

Although I know, I am a little surprised to write this~~

See how to do it:

<TextView
    android:id="@+id/tab1"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#f67"
    android:gravity="center"
    android:text="Tab1"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/tab2" />


<TextView
    android:id="@+id/tab2"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#A67"
    android:gravity="center"
    android:text="Tab2"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@id/tab1"
    app:layout_constraintRight_toLeftOf="@+id/tab3" />


<TextView
    android:id="@+id/tab3"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#767"
    android:gravity="center"
    android:text="Tab3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@id/tab2"
    app:layout_constraintRight_toRightOf="parent" />

We add 3 textviews to pretend to be tabs. Let's look at the horizontal dependencies. The three tabs set constraints in pairs (that is, you are on our left, I am on your right), and the outermost one is set with parent constraints; in addition, we set the width to match_constraint, so, In this way, we have completed 3 tab equal divisions.

Take a look at the renderings:

You may say that LL is more flexible with weight, and can set the proportion occupied by a single.

Yes, that's right, we also support it, I haven't finished talking yet.

Now we can set a property for each tab:

app:layout_constraintHorizontal_weight

When you see this name, you should understand it. Suppose we set the values ​​to 2, 1, and 1 respectively.

The effect picture is:

Isn't it a surprise, don't worry, you said just now that I'm not as good as LL, now I want you to see some things that LL can't do with weight.

Here are some pictures from the official website:

As we said just now, the 3 tabs have dependencies set up in pairs, that is, similar to the following figure:

The horizontal is equivalent to forming a chain (Chains). The leftmost element in this chain becomes the chain head, and we can set some properties on it to determine the display effect of this chain:

The property is:

layout_constraintHorizontal_chainStyle

We have already seen an effect, that is divided by weight, can become weighted chain. The set condition is:

chainStyle=”spread”, the width of all controls is set to match_constraint, because the default is spread, so we have no display settings.

Its value can also be:

  • packed
  • spread_inside

I'll show them separately:

  1. spread + width is not 0

  1. spread + width is 0, and the distribution ratio can be controlled by weight (the above example)

  2. spread_inside + width is not 0

  1. packed + non-zero width

Well, that's almost it, we can form a Chain horizontally or vertically, and then set chainStyle in the Chain head to do some things.

The official website has a picture:

We have demonstrated the first four, and the last one is designed with a new bias attribute, don't worry, let's talk slowly~~

Well, here, we once again witnessed the power of ConstraintLayout.

Let's look at one last example.

Five, increase the floating button

A very common feature, we now want to add a floating button in the lower right corner.

See how to do it:

<android.support.constraint.ConstraintLayout 
    ...
    tools:context="com.zhy.constrantlayout_learn.MainActivity">

    <TextView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="#612"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.9" />

</....>

We append a TextView at the end to pretend to be our floating button. You can see that we set a fixed value, which is constrained to the lower right corner.

Under normal circumstances, we can set the distance from the right side and the bottom through the margin.

But here we try to use a few new properties:

layout_constraintHorizontal_bias
layout_constraintVertical_bias

That is to say, set the gap ratio of the upper and lower sides to 90% and 10% respectively. This is easy to understand. As we said before, when there is no bias attribute, the pulling force on both sides is the same, but you can use bias to control which side has a larger force~~ Understood~

So, this property can be used to control the "pull" on both sides before constraining.

Let's take a look at the renderings:

So here, we have basically introduced the properties of ConstraintLayout:

Let's take a look:

layout_constraintLeft_toLeftOf 
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf

# 即文章的baseline对齐
layout_constraintBaseline_toBaselineOf

# 与left,right类似
layout_constraintStart_toEndOf 
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf

# margin不需要解释
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom

layout_constraintHorizontal_bias  
layout_constraintVertical_bias  

layout_constraintHorizontal_chainStyle
layout_constraintVertical_chainStyle

layout_constraintVertical_weight

Guideline 

It seems that there is a special one called Guideline.

Okay, go ahead~

6. Try to use Guideline

android.support.constraint.GuidelineThis class is relatively simple and is mainly used for auxiliary layouts, that is, similar to auxiliary lines, horizontal and vertical. The layout will not be displayed on the interface.

So it has a property as:

android:orientation takes the values ​​"vertical" and "horizontal".

In addition, there is another attribute that determines the position of the auxiliary line:

  • layout_constraintGuide_begin
  • layout_constraintGuide_end
  • layout_constraintGuide_percent

The attribute value location can be determined by one of the above three attributes.

begin=30dp, it can be considered that there is an auxiliary line 30dp from the top, and it is determined whether it is horizontal or vertical according to the orientation.

end=30dp, which is the distance from the bottom.
percent=0.8 is 80% from the top.

Ok, let's look at an example. For our floating button just now, I decided to position it through two auxiliary lines, one horizontally at 80% from the bottom and one vertically at 80% from the top. The floating button is positioned where they cross. .

<android.support.constraint.ConstraintLayout 
    ...
    tools:context="com.zhy.constrantlayout_learn.MainActivity">

    <android.support.constraint.Guideline
        android:id="@+id/guideline_h"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.8" />


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

    <TextView
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="#612"
        app:layout_constraintLeft_toRightOf="@id/guideline_w"
        app:layout_constraintTop_toBottomOf="@id/guideline_h" />

</....>

I feel like I don't need to explain it~~ Take a look at the renderings:

At this point, the properties are basically finished~

As you can see, the above rather complicated layout has no nesting in ConstraintLayout at all!

6. Summary

This article basically introduces all the properties supported by ConstraintLayout through the actual buttons. The full text does not mention drag and drop, because when the interface is complicated, it is too difficult to achieve perfect drag and drop, and no one expects it. See Don't understand the layout properties after dragging and dropping~

Therefore, I suggest handwriting as much as possible. Through the process of this article, although there are more than 20 supported attributes, it is not difficult to remember after classification.

Well, after thinking about it for a long time, how to introduce all the attributes through a case, in general, it is still completed, give yourself a thumbs up.


If you support me, you can follow my official account, and I will push new knowledge every day~

Welcome to pay attention to my WeChat public account: hongyangAndroid
(you can leave me a message for the articles you want to learn, support submission)

refer to

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325685504&siteId=291194637