Animating completely different widgets in your Android app had at all times been a painful expertise for builders. Nonetheless, all that modified with the introduction of the MotionLayout
subclass in Android.
You need to use MotionLayout
in your app to deal with widget animations from one state to a different. MotionLayout
was added as a subclass of the ConstraintLayout
class in model 2.0. Assist for MotionLayout
goes way back to API degree 14 with the assistance of a backwards-compatible help library.
Some helpful and fascinating options of the category embody animation of various structure properties in addition to help for seekable transitions. The help for keyframes in MotionLayout
is solely cherry on high. This lets you create your individual totally personalized transitions.
On this tutorial, you’ll discover ways to create animations inside your Android app utilizing MotionLayout
.
Add Dependencies
Step one earlier than you can begin utilizing MotionLayout
in your Android app includes including ConstraintLayout
as a dependency to your venture. That is included by default in all Android initiatives now. Nonetheless, you need to nonetheless ensure that any venture that makes use of MotionLayout
makes use of a model above 2.0.0 for the ConstraintLayout
as its dependency.
You may examine your individual venture dependencies by opening the construct.gradle file and on the lookout for this line beneath dependencies.
1 |
implementation 'androidx.constraintlayout:constraintlayout:2.1.4' |
The model quantity on the finish will change infrequently. So, don’t fret a couple of mismatch. The necessary factor to recollect is that it needs to be no less than 2.0.0.
Outline the App Format
If you’re creating a brand new app whereas following by this tutorial, you will notice that the activity_main.xml file is utilizing ConstraintLayout
for widget placement. We must substitute all cases of ConstraintLayout
in our structure file with MotionLayout
.
The simplest approach to try this is to change your structure from Code view to both Break up or Design View. You’ll discover a Element Tree panel on the left facet. Open the panel and you will notice the ConstraintLayout
in use. Proper click on on it and choose Convert to MotionLayout as proven within the picture under.
This can lead to a brand new pop-up window letting you recognize that the conversion to MotionLayout
will end result within the creation of a separate MotionScene
file. Click on the Convert button.
Your activity_main.xml file ought to now have the next XML code:
1 |
<?xml model="1.0" encoding="utf-8"?>
|
2 |
<androidx.constraintlayout.movement.widget.MotionLayout xmlns:android="https://schemas.android.com/apk/res/android" |
3 |
xmlns:app="http://schemas.android.com/apk/res-auto" |
4 |
xmlns:instruments="http://schemas.android.com/instruments" |
5 |
android:layout_width="match_parent" |
6 |
android:layout_height="match_parent" |
7 |
app:layoutDescription="@xml/activity_main_scene" |
8 |
instruments:context=".MainActivity"> |
9 |
|
10 |
<TextView
|
11 |
android:id="@+id/textView" |
12 |
android:layout_width="wrap_content" |
13 |
android:layout_height="wrap_content" |
14 |
android:textual content="Hiya World!" |
15 |
app:layout_constraintBottom_toBottomOf="mum or dad" |
16 |
app:layout_constraintEnd_toEndOf="mum or dad" |
17 |
app:layout_constraintStart_toStartOf="mum or dad" |
18 |
app:layout_constraintTop_toTopOf="mum or dad" /> |
19 |
|
20 |
</androidx.constraintlayout.movement.widget.MotionLayout>
|
Let’s add a Button
widget to our structure. We’ll design our app in such a approach {that a} click on on the button will make our TextView
widget bounce up a bit and improve in dimension. Add the next XML under the TextView
widget so as to add a button that claims Bounce and stays 20sp under our TextView
widget.
1 |
<Button
|
2 |
android:id="@+id/button" |
3 |
android:layout_width="wrap_content" |
4 |
android:layout_height="wrap_content" |
5 |
android:textual content="Bounce" |
6 |
android:textSize="18sp" |
7 |
android:layout_marginTop="20sp" |
8 |
app:layout_constraintEnd_toEndOf="mum or dad" |
9 |
app:layout_constraintStart_toStartOf="mum or dad" |
10 |
app:layout_constraintTop_toBottomOf="@id/textView" /> |
Enhancing the MotionScene File
Do you do not forget that Android Studio confirmed us a pop-up window which talked about that the conversion of our ConstraintLayout
to MotionLayout
will lead to creation of a MotionScene
file? The identify of that MotionScene
file is activity_main_scene.xml. You will discover it beneath res > xml > activity_main_scene.xml in your venture.
A reference to the movement scene file can be current in our activity_main.xml file beneath the app:layoutDescription
attribute. The activity_main_scene.xml file accommodates the next code:
1 |
<?xml model="1.0" encoding="utf-8"?>
|
2 |
<MotionScene
|
3 |
xmlns:android="http://schemas.android.com/apk/res/android" |
4 |
xmlns:movement="http://schemas.android.com/apk/res-auto"> |
5 |
|
6 |
<Transition
|
7 |
movement:constraintSetEnd="@+id/finish" |
8 |
movement:constraintSetStart="@id/begin" |
9 |
movement:period="1000"> |
10 |
<KeyFrameSet>
|
11 |
</KeyFrameSet>
|
12 |
</Transition>
|
13 |
|
14 |
<ConstraintSet android:id="@+id/begin"> |
15 |
</ConstraintSet>
|
16 |
|
17 |
<ConstraintSet android:id="@+id/finish"> |
18 |
</ConstraintSet>
|
19 |
</MotionScene>
|
As you’ll be able to see, the scene file accommodates a root MotionScene
tag with different tags inside it that management the precise movement or animation of a widget.
The Transition
tag inside MotionScene
defines how the animation will proceed based mostly on its begin and finish ConstraintSets
. Every ConstrainSet
can comprise a Constraint
tag which you need to use to supply constraint and think about particular attribute values.
There are three issues that we need to change about our TextView
with every button click on. The colour of the textual content ought to change from black to teal_700. These values are outlined within the colours.xml file. The spacing between the TextView
widget and the Button
ought to improve to 40sp. The TextView
widget ought to scale as much as twice the unique dimension.
Right here is the XML that we are able to use inside our MotionScene
file to make our textView
jumpy.
1 |
<?xml model="1.0" encoding="utf-8"?>
|
2 |
<MotionScene
|
3 |
xmlns:android="http://schemas.android.com/apk/res/android" |
4 |
xmlns:movement="http://schemas.android.com/apk/res-auto"> |
5 |
|
6 |
<Transition
|
7 |
movement:constraintSetEnd="@+id/finish" |
8 |
movement:constraintSetStart="@id/begin" |
9 |
movement:period="200" |
10 |
movement:motionInterpolator="easeIn"> |
11 |
<OnClick
|
12 |
movement:targetId="@id/button" |
13 |
movement:clickAction="transitionToEnd" /> |
14 |
</Transition>
|
15 |
|
16 |
<ConstraintSet
|
17 |
android:id="@+id/begin"> |
18 |
<Constraint
|
19 |
android:id="@id/textView"> |
20 |
<CustomAttribute
|
21 |
movement:attributeName="textColor" |
22 |
movement:customColorValue="@coloration/black" /> |
23 |
</Constraint>
|
24 |
</ConstraintSet>
|
25 |
|
26 |
<ConstraintSet
|
27 |
android:id="@+id/finish"> |
28 |
<Constraint
|
29 |
android:id="@id/textView" |
30 |
android:scaleX="2" |
31 |
android:scaleY="2"> |
32 |
<Format
|
33 |
android:layout_marginBottom="40sp" |
34 |
android:layout_width="wrap_content" |
35 |
android:layout_height="wrap_content" |
36 |
movement:layout_constraintBottom_toTopOf="@id/button" /> |
37 |
<CustomAttribute
|
38 |
movement:attributeName="textColor" |
39 |
movement:customColorValue="@coloration/teal_700" /> |
40 |
</Constraint>
|
41 |
</ConstraintSet>
|
42 |
</MotionScene>
|
The attributes inside Transition
specify the period of animation in milliseconds in addition to the interpolation technique used to calculate intermediate values. We additionally use the non-compulsory OnClick
tag to specify when the transition ought to set off. The targetId
attribute determines which view will set off the animation. In our case, we use our button because the set off ingredient. The clickAction
attribute sepcifies what ought to occur as soon as the person clicks our button. On this case, we now have set its worth to transitiontoEnd
. Different doable values are toggle
, transitionToStart
, jumpToEnd
, and jumpToStart
.
After that, we outline our ConstraintSet
tags which decide what our widget will seem like at first and the tip of the animation. You can even think about using the Movement Editor when you do not choose to jot down all of the XML your self. This may also offer you a good suggestion of the way in which your structure appears to be like at first and finish of the animation.
Strive operating your app on both the emulator or a bodily gadget now. You need to see the TextView
bounce up, change coloration, and improve in dimension.
Controlling the Animation Programmatically
Whereas it was doable for us to animate our textual content just by writing some XML, you’ll most likely like extra management over the animation. Executing the animation programmatically provides you the choice to do different duties based mostly on the general progress of the animation.
Add the next line to your Button
widget XML to name a technique named begin()
outlined in our MainActivity.kt file:
1 |
android:onClick="begin" |
Outline a technique referred to as begin()
inside the MainActivity
class slightly below onCreate()
. It ought to have the next code:
1 |
enjoyable begin(v: View) { |
2 |
val motionContainer = findViewById<MotionLayout>(R.id.motion_container) |
3 |
motionContainer.transitionToEnd(); |
4 |
}
|
We start by first getting a reference to our MotionLayout
. Within the subsequent line, we use the transitionToEnd()
technique to transition to animation from the values within the beginning ConstraintSet
to the ending ConstraintSet
.
You may connect a transition listener to your MotionLayout
widget to observe the progress of the animation and deal with what occurs at completely different occasions. The TransitionListener
interface has 4 summary strategies. Android Studio will generate stubs for all these strategies for you robotically. Your code under the decision to transitionToEnd()
ought to seem like this now:
1 |
val jumpButton = findViewById<Button>(R.id.button) |
2 |
val greeting = findViewById<TextView>(R.id.textView) |
3 |
|
4 |
motionContainer.setTransitionListener( |
5 |
object: MotionLayout.TransitionListener { |
6 |
|
7 |
override enjoyable onTransitionStarted( |
8 |
motionLayout: MotionLayout?, |
9 |
startId: Int, |
10 |
endId: Int |
11 |
) { |
12 |
jumpButton.setBackgroundColor(Coloration.BLACK); |
13 |
}
|
14 |
|
15 |
override enjoyable onTransitionChange( |
16 |
motionLayout: MotionLayout?, |
17 |
startId: Int, |
18 |
endId: Int, |
19 |
progress: Float |
20 |
) { |
21 |
|
22 |
}
|
23 |
|
24 |
override enjoyable onTransitionCompleted( |
25 |
motionLayout: MotionLayout?, |
26 |
currentId: Int) { |
27 |
if(currentId == R.id.finish) { |
28 |
greeting.textual content = "Good Night!"; |
29 |
}
|
30 |
}
|
31 |
|
32 |
override enjoyable onTransitionTrigger( |
33 |
motionLayout: MotionLayout?, |
34 |
triggerId: Int, |
35 |
optimistic: Boolean, |
36 |
progress: Float |
37 |
) { |
38 |
|
39 |
}
|
40 |
}
|
41 |
)
|
We start by getting a reference to the TextView
widget and the Button
widget.
Contained in the TransitionListener
, the onTransitionStarted()
technique fires when the transition is about to begin. It accepts the outlined MotionLayout
as the primary parameter. The second and third parameters are the Ids of the beginning and finish constraint units.
We name the setBackgroundColor()
technique on the jumpButton
to vary its coloration to black as soon as the transition begins.
The onTransitionCompleted()
technique fires when the transition is full. It accepts two parameters. The primary one is the reference to our MotionLayout
. The second is Id of the ConstraintSet
at the moment relevant to the structure.
We examine if the currentId
matches the Id of our finish ConstraintSet
. The greeting textual content modifications to Good Night! if there’s a match. You may additionally do different issues right here comparable to taking the transition again to the preliminary state by making a name to transitionToStart()
.
Clicking the Bounce button this time will replace the textual content and alter the button coloration as nicely.
Ultimate Ideas
On this tutorial, you realized the right way to animate completely different widgets in your exercise utilizing MotionLayout
. It’s doable so that you can animate layouts by simply utilizing XML. Nonetheless, you may get granular management over the animation when you use code to do the animation. It additionally means that you can do different issues throughout completely different levels of the animation.
Android Studio additionally comes with a Movement Editor that helps you rapidly outline complicated transitions. Additionally, you will be capable to see the preliminary and closing levels of the animation when utilizing the Movement Editor.