introduce

This series has covered the basic usage of ConstraintLayout. Now that you are familiar with the basics of ConstraintLayout, I recommend that you read my previous articles if you are not familiar with it.

The basic idea behind creating an animation with ConstraintLayout is that we create two different layouts, each with different constraints, and use its animation framework to switch between the two constraints.

Traditional animation

In the past, when we created simple animations, we used to use

  • View Animation
  • Drawable Animation
  • Property Animation

All three are very easy and convenient for simple animations, especially if we’re only animating a particular View. However, when we need to create complex animations, especially when multiple views on the entire page perform animations at the same time, these methods are not enough and require a lot of work.

Another way is to use the Transition Framework to animate Shared elements, which we’ll talk about later.

ConstraintLayout animation

We use an example to illustrate the creation of a ConstraintLayout animation.

  1. First, we create our first layout (activity_main.xml), which is our initial layout.
  • Effect:

  • Code:

<?xml version="1.0" encoding="utf-8"? >
<android.support.constraint.ConstraintLayout
    android:id="@+id/cl_root"
    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=".MainActivity">

    <TextView
        android:id="@+id/tv_score"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Score: 8.3"
        app:layout_constraintStart_toStartOf="@+id/tv_name"
        app:layout_constraintTop_toBottomOf="@+id/tv_name" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="8dp"
        android:text=Wreck-it Ralph 2
        android:textColor="# 282828"
        android:textSize="20sp"
        app:layout_constraintStart_toEndOf="@+id/iv_poster"
        app:layout_constraintTop_toTopOf="@+id/iv_poster" />

    <ImageView
        android:id="@+id/iv_poster"
        android:layout_width="120dp"
        android:layout_height="160dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:scaleType="centerCrop"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/wreck_it_ralph" />

</android.support.constraint.ConstraintLayout>
Copy the code

After our initial layout is created, we need to create an end-of-animation layout so that the animation framework knows what the layout will look like after the animation is executed.

  1. Create the end-of-animation layout (activity_main_detail.xml).
  • Effect:

  • Code:
<?xml version="1.0" encoding="utf-8"? >
<android.support.constraint.ConstraintLayout
    android:id="@+id/cl_root"
    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=".MainActivity">

    <TextView
        android:id="@+id/tv_score"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="52dp"
        android:text="Score: 8.3"
        app:layout_constraintBottom_toBottomOf="@+id/tv_name"
        app:layout_constraintStart_toEndOf="@+id/tv_name"
        app:layout_constraintTop_toTopOf="@+id/tv_name"/>

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:text=Wreck-it Ralph 2
        android:textColor="# 282828"
        android:textSize="20sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/iv_poster"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="65dp"
        android:scaleType="centerCrop"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@mipmap/wreck_it_ralph" />

</android.support.constraint.ConstraintLayout>
Copy the code

This is what the page looks like after we perform the animation. So now that we have the starting and ending layouts, how do we animate the transition between the two layouts?

The answer is through Android’s TransitionManager.

  1. Use the TransitionManager to perform the animation
  • Code (mainactivity.java)
package cn.examplecode.constraintlayoutdemo;

import android.support.constraint.ConstraintLayout;
import android.support.constraint.ConstraintSet;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.transition.TransitionManager;

public class MainActivity extends AppCompatActivity {

    private ConstraintLayout mConstraintLayout;
    private boolean mIsDetail;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mConstraintLayout = findViewById(R.id.cl_root);

        ConstraintSet constraintSet1 = new ConstraintSet();
        ConstraintSet constraintSet2 = new ConstraintSet();

        constraintSet2.clone(this, R.layout.activity_main_detail);
        constraintSet1.clone(mConstraintLayout);

        findViewById(R.id.iv_poster).setOnClickListener(v -> {
            TransitionManager.beginDelayedTransition(mConstraintLayout);
            if(! mIsDetail) { constraintSet2.applyTo(mConstraintLayout); mIsDetail =true;
            } else {
                constraintSet1.applyTo(mConstraintLayout);
                mIsDetail = false; }}); }}Copy the code

Let’s explain the above code. First we noticed that we used this class, ConstraintSet, which is a ConstraintSet that holds the constraints of all elements on the layout. Because we need to animate between two layouts, we need to create objects for both constraint sets.

ConstraintSet constraintSet1 = new ConstraintSet();
ConstraintSet constraintSet2 = new ConstraintSet();
Copy the code

After creating the constraint set objects, we need to set the constraints corresponding to each constraint set:

constraintSet2.clone(this, R.layout.activity_main_detail);
constraintSet1.clone(mConstraintLayout);
Copy the code

Here we apply the constraints of the current layout to constraintSet1 and the constraints of the target layout to constraintSet2.

Next we perform the animation:

TransitionManager.beginDelayedTransition(mConstraintLayout); ConstraintSet2 constraintSet2. ApplyTo (mConstraintLayout); ConstraintSet1 constraintSet1. ApplyTo (mConstraintLayout);Copy the code

End result:

With just a few lines of code, you can achieve complex animations! Of course, to illustrate the ConstraintLayout animation creation, the layout is relatively simple. If you need to animate a complex layout, the advantages of this approach are obvious. If you use the traditional method of creating an animation, it can take a lot of time and code to implement.

Problems discussed

Why create two layout files?

Some people may think that creating two layout files is not a good idea, because there is duplicate code in both layouts. Is that a good idea?

It’s actually not as bad as you might think, the purpose of creating two layout files is just to let the animation frame know the different constraints, and then apply the different constraints to the transition animation. You can remove the attributes that are not related to the constraints from the layout. If you really don’t like creating two layout files, of course you can describe different constraints in your code. This obviously adds a lot of complexity and code.

How is it different from animating Shared elements?

This is also possible with shared element animation, but with shared element animation you also need to create two layouts, and the key difference is that when you animate ConstraintLayout, the View before and after the animation is the same View object. When you animate shared elements, the views before and after the animation are two different View objects!

Series of summary

This is the last post in a series of blog posts called Grasp ConstraintLayout. By the end of this series, you have mastered most of the functions of ConstraintLayout.

ConstraintLayout, combined with my Data Binding series, will greatly reduce the workload of Android development and increase productivity.

Thanks for your support!

For more questions, please refer to my other Android-related blog: My blog address