Reading Instructions:

  • Does this article assume that the reader already knows how to use itConstraintLayout.
  • This article assumes that the reader hasMotionLayoutHave a basic understanding, know how to createMotionSceneFiles, and how to use themMotionLayoutIn the twolayoutCreate transition animations between layout files. If you don’t know anything about this, I suggest you read itMotionLayout Basics tutorial.
  • It is suggested that readers practice in the process of reading, which is helpful for better understanding. If you are not convenient now, it is suggested to read later.
  • Because the official document is not complete, part of the content comes from the author’s personal understanding, if there is any mistake, welcome to correct.

This article isMotionLayout Basics tutorialThe first2Chapter, mainly introduces to the reader how toMotionSceneThe scenario constraints are defined in the file and how custom attributes are used.

Define the constraints in the MotionScene file

Can be found in<MotionScene>Element.<ConstraintSet>The child element defines a set of scene constraints, and the<ConstraintSet>Element.<Constraint>Element defines a singleViewAttribute constraint of.

Example: Define the constraint set for the End scene in the MotionScene file

<?xml version="1.0" encoding="utf-8"? >
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <! Define the constraint set for the End scene
    <ConstraintSet android:id="@+id/activity_main_end">

        <! Define the constraint on the View with id image in the layout -->
        <Constraint
            android:id="@+id/button"
            android:layout_width="56dp"
            android:layout_height="56dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0" />

    </ConstraintSet>

    <! Start scene is the layout file, End scene is the constraint set defined in the MotionScene file.
    <Transition
        app:constraintSetStart="@layout/activity_main"
        app:constraintSetEnd="@id/activity_main_end"
        app:duration="1000">

        <OnClick
            app:clickAction="toggle"
            app:targetId="@id/button" />

    </Transition>

</MotionScene>
Copy the code

In fact, you can takeStartThe constraint set of the scene is defined inMotionSceneIn the file, you can also putEndThe constraint set of the scene is defined inMotionSceneFile. Or only inMotionSceneThe file defines one of these two to be used in another scenariolayoutLayout file definition.

Suggestion: It is recommended that the constraint sets of both Start and End scenarios be defined in the MotionScene file. Because some features of the MotionLayout framework, such as custom properties (described in the next section), depend on the Start scene in the MotionScene file, these features may not be available if the Start scene is not defined in the MotionScene file.

Example: Define the Start and End constraints in the MotionScene file (this example is divided into the following two steps)

1. Create a layout file:

File name: activity_main.xml

<?xml version="1.0" encoding="utf-8"? >
<androidx.constraintlayout.motion.widget.MotionLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/activity_main_motion_scene">

    <Button
        android:id="@+id/button"
        android:layout_width="56dp"
        android:layout_height="56dp"
        android:background="@color/colorPrimary"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="1.0" />

</androidx.constraintlayout.motion.widget.MotionLayout>
Copy the code

Note: Layout files are still needed, but defining both the Start and End constraints in the MotionScene file does not eliminate the need for layout files.

Layout file preview:

2. To createMotionSceneFile:

File name: activity_main_motion_scene.xml

<?xml version="1.0" encoding="utf-8"? >
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <! -- Define the attribute constraint set for the Start scenario -->
    <ConstraintSet android:id="@+id/activity_main_start">

        <! Define layout View attribute constraint with id as button -->
        <Constraint
            android:id="@id/button"
            android:layout_width="56dp"
            android:layout_height="56dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="1.0" />

    </ConstraintSet>


    <! Define the attribute constraint set of the End scene -->
    <ConstraintSet android:id="@+id/activity_main_end">

        <! Define layout View attribute constraint with id as button -->
        <Constraint
            android:id="@+id/button"
            android:layout_width="56dp"
            android:layout_height="56dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0" />

    </ConstraintSet>

    <! Start and End scenes are constraint sets defined in the MotionScene file.
    <Transition
        app:constraintSetStart="@id/activity_main_start"
        app:constraintSetEnd="@id/activity_main_end"
        app:duration="1000">

        <OnClick
            app:clickAction="toggle"
            app:targetId="@id/button" />

    </Transition>

</MotionScene>
Copy the code

<ConstraintSet>Element attribute description:

  • android:id: sets the current constraint setid. thisidValues can be<Transition>Elements of theapp:constraintSetStartorapp:constraintSetEndReferences.

<Constraint>Element attribute description:

  • android:id: The one to which the current constraint is associatedViewid.
  • app:transitionEasing: Defines the easing curve used to animate to this point. The value can be a string (for example"The curve (1.0, 0,0,1.0)") can also be one of the following enumerated values:
    • standardStandard:
    • accelerate: to speed up
    • decelerate: slow down
    • linear: linear

Tip 1: The app:transitionEasing attribute of the

element is similar to the app:motionInterpolator attribute of the
element, which is used to define interpolators for Transition animations. The difference is that the app:transitionEasing property of the

element defines the interpolator for the transition animation of a single View, The app:motionInterpolator of the
element defines an interpolator for the entire Transition animation.

Tip 2: If you specify an APP: transitionInterpolator for the

element, this interpolator will apply to the transition animation of the View at the same time as the global interpolator specified by the app:motionInterpolator attribute. Instead of replacing the global interpolator specified by the APP :motionInterpolator property.

Tip 3:

the app:transitionEasing attribute value for the

element should be specified in the Start scenario. (As tested) Specifying app:transitionEasing only in the End scenario does not work.

Tip 4: You can use a string of the form “curve(1.0,0,0,1.0)” to set a soft curve for the app:transitionEasing property of the

element. The MotionLayout framework will generate an interpolator based on this gentle curve.

  • App :transitionPathRotate: [float value] Rotate the object relative to the path taken (arc path/keyframe dependent).
  • app:drawPath: Draws the transition animation path (debug, keyframe related). It can be one of the following enumerated values:
    • none
    • path
    • pathRelative
    • deltaRelative
    • asConfigured
    • rectangles
  • app:progress: floating point value in relationViewOn the callsetProgress(float)Method (used with nestedConstraintLayoutInteraction)

As I said,<Constraint>The element is used to define a singleViewProperty constraint, which supports theViewAll of theConstraintLayoutProperty defines constraints, as well as constraints toViewThe following standard attributes define constraints for:

  • android:visibility
  • android:alpha
  • android:elevation
  • android:rotation
  • android:rotationX
  • android:rotationY
  • android:scaleX
  • android:scaleY
  • android:translationX
  • android:translationY
  • android:translationZ

whenViewStandard properties orConstraintLayoutWhen the property changes,MotionLayoutTransition animations are automatically applied.

Custom attributes

The MotionLayout control only detects layout-related property changes, such as the standard and ConstraintLayout properties. Other property changes, such as the background color of the View, are not detected, so you need to use custom properties.

in<Constraint>Element.<CustomAttribute>Child element to specify custom attributes.

Ex. :

<?xml version="1.0" encoding="utf-8"? >
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <! -- Define the attribute constraint set for the Start scenario -->
    <ConstraintSet android:id="@+id/activity_main_start">

        <! Define the constraint on the View with id image in the layout -->
        <Constraint
            android:id="@id/button"
            android:layout_width="56dp"
            android:layout_height="56dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="1.0">

            <! -- Use custom attributes -->
            <CustomAttribute
                app:attributeName="backgroundColor"
                app:customColorValue="@color/colorPrimary" />

        </Constraint>

    </ConstraintSet>


    <! Define the attribute constraint set of the End scene -->
    <ConstraintSet android:id="@+id/activity_main_end">

        <! Define the constraint on the View with id image in the layout -->
        <Constraint
            android:id="@+id/button"
            android:layout_width="56dp"
            android:layout_height="56dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0">

            <! -- Use custom attributes -->
            <CustomAttribute
                app:attributeName="backgroundColor"
                app:customColorValue="@color/colorAccent" />

        </Constraint>

    </ConstraintSet>

    <Transition
        app:constraintSetEnd="@id/activity_main_end"
        app:constraintSetStart="@id/activity_main_start"
        app:duration="1000">

        <OnClick
            app:clickAction="toggle"
            app:targetId="@id/button" />

    </Transition>

</MotionScene>
Copy the code

Effect preview:

<CustomAttribute>Element attribute description:

  • app:attributeNameProperty specifies the name of the custom property(e.g."backgroundColor").The associatedViewThere must be a pair associated with the namegetter/settermethods(e.g.getBackgroundColor()/setBackgroundColor(int color)).
  • The rest of the attributes are used to set the values of the custom attributes.The following is required based on the value type of the custom attributeXMLProperty to set the value of the custom property:
    • App :customColorValue: Sets the value of the property (color type).
    • App: customColorDrawableValue: set the value of the attribute type (color).
    • App :customIntegerValue: Set the value of the property (integer type).
    • App :customFloatValue: Set the value of the property (floating-point type).
    • App :customStringValue: Sets the value of the property (as a string).
    • App :customDimension: Sets the value of the property (size type).
    • App :customPixelDimension: Sets the value of the property (size type).
    • App :customBoolean: Sets the value of the property (Boolean type).

conclusion

This article is part 2 of the MotionLayout Basics Tutorial. After reading these two articles, you should have a basic understanding of MotionLayout.

The main purpose of these two articles is to introduce the reader to the basics of MotionLayout so that the reader can get started and learn from it. If you want to learn more about MotionLayout, you are recommended to read the following three articles:

  • Introduction to “Translation” MotionLayout (Part II)
  • Introduction to “Translation” MotionLayout (Part III)
  • Introduction to “Translating” MotionLayout (Part IV)