This is the 14th day of my participation in Gwen Challenge

Features,

Chain (Chain)

Chains provide row-like behavior on a single axis (horizontal or vertical). The other axis can be constrained independently.

If a set of controls are linked together by a two-way connection, they are treated as chains (as shown below, a Chain of minimal units with only two controls).

Chain header Horizontally, the Chain header is the left-most control of the Chain. Vertically, the Chain header is the topmost control of the Chain.

Chain margin If a margin is defined during connection, the Chain changes. In the SPREAD CHAIN, margins are removed from the allocated space.

Chain Style

When the layout_constraintHorizontal_chainStyle or layout_constraintVertical_chainStyle attribute is set to the first element of the Chain, The Chain changes according to a specific style (the default style is CHAIN_SPREAD). The style type is as follows:

  • CHAIN_SPREADElements are scattered (default style)
  • inCHAIN_SPREADMode if some controls are set toMATCH_CONSTRAINT, the control will divide all remaining space evenly and “eat”
  • CHAIN_SPREAD_INSIDEThe elements on either side of the Chain are attached to the parent container, and the other elements are adopted in the remaining spaceCHAIN_SPREADmodel
  • CHAIN_PACKEDAll controls in the Chain are merged and centered in the remaining space

Weighted Chains

The default Chain is to evenly distribute elements across the available space. If one or more of the elements use the MATCH_CONSTRAINT attribute, they fill out the remaining space evenly. The attributes layout_constraintHorizontal_weight and layout_constraintVertical_weight control how elements using MATCH_CONSTRAINT divide space equally. For example, if a Chain contains two elements using MATCH_CONSTRAINT, and the first element uses a weight of 2 and the second element uses a weight of 1, the space taken up by the first element is twice as much as the second element.

When using margins on elements in a chain, the margins are additive.

For example, on a horizontal chain, if one element defines a right margin of 10dp and the next element defines a left margin of 5dp, the resulting margin between those two elements is 15dp.

**Margins and chains **

This property was added in version 1.1

When margins are used on elements in a chain, margins are additive.

For example, on a horizontal chain, if one element defines the right margin of 10DP and the next element defines the left margin of 5DP, the resulting margin between the two elements is 15DP. When calculating the remaining space of the chain used to locate the item, the item and its margins are considered simultaneously. The remaining space does not contain margins.

Virtual Helper Objects

In addition to the built-in capabilities detailed earlier, you can use the helper tools in ConstraintLayout to help you layout. Currently, the Guideline object allows you to create horizontal and vertical guidelines relative to ConstraintLayout container positioning. You can then locate the widget by limiting it to such guidance. In 1.1, barriers and groups were also added.

Guideline

Guideline is not displayed on the device (they are labeled view.gone) and is only used for layout purposes. They work only in ConstraintLayout. The utility is to help add constraints to our controls. It’s like the idea of guides in Photoshop. As shown below, create a vertical guide line that can toggle percentages or actual distances. Which one to use depends on the actual situation.

Barrier

Many times controls change in size according to the amount of data they contain. It is difficult to set a Barrier between controls when you have multiple controls that are bound by each other. A Barrier, like the GuideLine, is a virtual View that is not visible to the interface and is used to assist in layout. The difference between a Barrier and GuideLine is that its properties can be determined by multiple views

Barrier can use the following properties:

  • RrierDirection: specifies the location of the Barrier. The values are bottom, top, start, end, left, and right

  • Constraint_referenced_ids: Specifies the ID of the control referenced by the Barrier

  • BarrierAllowsGoneWidgets: Defaults to true and creates a Barrier where the control referred to by the Barrier has already been resolved. If set to false, the Gone control is not taken into account

Here’s a very simple example:

We have three TextViews: textView1 and textView2 on the left and textView3 on the right. TextView3 is bound to the right of textView1, and it works as expected.

But things get complicated when you need to support multiple languages. We have a problem if we add German, because in English textView1 is longer than textView2, but in German textView2 is longer than textView1:

The problem here is textView3 is still relative to textView1, so textView2 is inserted directly into textView3. It looks more obvious in the design view (the one with the white background).

A View can only set one View as an anchor, so if you set one View you can’t set the other one, so the traditional method is to use a TableLayout, Or wrap textView1 & textView2 inside a vertical LinearLayout and then have textView3 constrained behind that LinearLayout. Hence the Barrier, which can set up N views as anchors.

Barrier is a virtual view, similar to Guideline, used to constrain objects. The difference between a Barrier and Guideline is that it is determined by the size of multiple views. In this case, we don’t know which textView1 or textView2 is longer, so we can create a Barrier based on the width of both views. We can constrain textView3 behind the Barrier.

Create Barriers in the editor

To create a vertical barrier, select create a vertical barrier from the context menu:

Note: Android Studio2.3 does not seem to have this menu, Android Studio3.0 does, but the submenu in the Help menu group is somewhat different from the illustration below.

You can see the Barrier in the Component tree (left panel near the bottom).

We can change its position by dragging (optional) :

Next we need to set the Barrier direction. TextView1 and textView2 will follow each other, so we need to set the direction to end:

The final step is to tell the Barrier which views it is relative to. I don’t use constraints because constraints are usually one-to-one, but in this case it’s multiple views. We need to specify the VIEW ID referenced by the Barrier by dragging the View onto the Component tree:

Once defined, these references are listed as the children of the Barrier. You can also see in the blue panel that the Barrier jumps to its new location (the vertical dotted line).

Now that the Barrier is defined, it’s just a matter of changing textView3’s constraint from relative to textView1 to relative to the Barrier:

And then textView3 comes after textView2.

To see the effect as a whole, switch languages and you’ll see that the Barrier automatically comes after the wider textView, which indirectly puts textView3 in the correct position:

Create Barriers in THE XML

The XML code is actually quite simple:


      
<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/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="16dp"
    android:text="@string/warehouse"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

  <TextView
    android:id="@+id/textView2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="8dp"
    android:text="@string/hospital"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textView1" />

  <androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier7"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="end"
    app:constraint_referenced_ids="textView2,textView1" />

  <TextView
    android:id="@+id/textView3"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:text="@string/lorem_ipsum"
    app:layout_constraintStart_toEndOf="@+id/barrier7"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code

barrierAllowsGoneWidgets

Now button3 and button1 button2 are top aligned. What if button1 is Gone?

After button1 is gone, it will turn into a dot, so button3 will have no problem matching the parent layout. But sometimes it’s not meets our requirements, we hope that we don’t focus on the Barrier Gone View, so Google provides properties barrierAllowsGoneWidgets, set to false, not concerned about the View Gone, After button1 is gone,button3 is no longer aligned with the parent layout,but with button2.

What makes barriers special is the Barrier elements themselves. The app:barrierDirection attribute determines the direction of the Barrier – it is placed after the referenced view. The referenced views are a list of ids of the views in the layout, separated by commas.

Borrow a picture from medium.com/androiddeve…

Group

With groups, you can group certain views together. This is not to be confused with normal ViewGroups in Android. A group in ConstraintLayout contains only a reference to a view ID and does not nest the views in the composition. This way, you can set the visibility of controls in a group simply by setting the visibility of the group, without setting the visibility of each view. This is useful for things like error screens or load screens, where some elements need to change their visibility at once

The available attributes are:

  • Constraint_referenced_ids: Specifies the ID of the referenced control.
<androidx.constraintlayout.widget.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, as the name suggests, is a Placeholder that can be converted into a valid view via 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.


      
<androidx.constraintlayout.widget.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/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.Placeholder
        android:id="@+id/placeholder"
        android:layout_width="96dp"
        android:layout_height="96dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:scaleType="centerInside"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/mail" />

    <ImageButton
        android:id="@+id/favorite"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_marginTop="16dp"
        android:background="# 00000000"
        android:scaleType="centerInside"
        android:src="@drawable/favorite"
        android:tint="#E64A19"
        app:layout_constraintEnd_toStartOf="@id/mail"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/mail"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_marginTop="16dp"
        android:background="# 00000000"
        android:scaleType="centerInside"
        android:src="@drawable/checked"
        android:tint="#512DA8"
        app:layout_constraintEnd_toStartOf="@id/save"
        app:layout_constraintStart_toEndOf="@id/favorite"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/save"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_marginTop="16dp"
        android:background="# 00000000"
        android:scaleType="centerInside"
        android:src="@drawable/star"
        android:tint="#D32F2F"
        app:layout_constraintEnd_toStartOf="@id/play"
        app:layout_constraintStart_toEndOf="@id/mail"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@+id/play"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_marginTop="16dp"
        android:background="# 00000000"
        android:scaleType="centerInside"
        android:src="@drawable/delete"
        android:tint="#FFA000"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/save"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Copy the code
class DemoFragment : Fragment(), View.OnClickListener {
    override fun onClick(v: View) {
        //call TransitionManager so and pass ConstraintLayout to perform smooth animation
        TransitionManager.beginDelayedTransition(mConstraintLayout);
        //finally set clicked view at placeholder
        mPlaceholder.setContentId(v.id)

    }

    private lateinit var dashboardViewModel: DashboardViewModel
    private lateinit var mConstraintLayout: ConstraintLayout
    private lateinit var mPlaceholder: Placeholder

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup? , savedInstanceState:Bundle?).: View? {
        dashboardViewModel =
                ViewModelProviders.of(this).get(DashboardViewModel::class.java)
        val root = inflater.inflate(R.layout.fragment_dashboard, container, false)
   
        val favorite: ImageButton = root.findViewById(R.id.favorite)
        favorite.setOnClickListener(this)
        val star : ImageButton = root.findViewById(R.id.star)
        star.setOnClickListener(this)
        val checked : ImageButton = root.findViewById(R.id.checked)
        checked.setOnClickListener(this)
        val delete : ImageButton = root.findViewById(R.id.delete)
        delete.setOnClickListener(this)

        mConstraintLayout = root.findViewById(R.id.constraintLayout)
        mPlaceholder = root.findViewById(R.id.placeholder)

        return root
    }
}
Copy the code

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

Visual editor

Refer to the following article for this section

Use the layout editor to build the interface

Construct a responsive UI using ConstraintLayout

Self-discipline gives you freedom — new poses for designing layouts

ConstraintLayout new Android features, ConstraintLayout

Future layout star – ConstraintLayout

demo

Quanqi.org/2016/05/20/…

Juejin. Cn/post / 684490…

Juejin. Cn/post / 684490…

www.jianshu.com/p/b3cd72524…

animation

Juejin. Cn/post / 684490…

www.jianshu.com/p/9c7503f47…

senior

Developer.android.com/reference/a…

Developer.android.com/reference/a…

Barriers Clone () in ConstraintSet 1.1.3

Constraint sets and animations

You can use ConstraintLayout with ConstraintSet to animate multiple elements at once.

A ConstraintSet holds only one ConstraintLayout constraint. You can create a ConstraintSet in your code or load it from a layout file. You can then apply ConstraintSet to ConstraintLayout, updating all constraints to match the constraints in ConstraintSet.

To make its animation effects, please use the support library in TransitionManager. BeginDelayedTransition () method. This feature will animate all layout updates in your ConstraintSet.

Here’s a video that covers the topic in more depth:

  • YouTube video link: Youtu. be/OHcfs6rStRo

    motionlaytout

Github.com/googlesampl…

Performance analysis

Mp.weixin.qq.com/s/gGR2itbY7…

Android. Jlelse. Eu/constraint -…

www.cnblogs.com/liujingg/p/…

reference

The official documentation

Read it carefully! ConstraintLayout is the official document

Why ConstraintLayout instead of any other layout?

Explain ConstraintLayout for Android version 1.1.0

Explain ConstraintLayout for Android

Future layout star – ConstraintLayout

The Barrier of ConstraintLayout

ConstraintLayout Guideline, Barrier, Chains and Groups

ConstraintLayout is new in version 1.1.2

What’s new with Constraint Layout 1.1.x?

ConstraintLayout interpret all