Build Complex Animations With MotionLayout in Jetpack Compose - Android Studio Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys and welcome back to a new video if you want to learn how you can make such a cool transition effect here using motion layout and comparable effects with motion layout pretty much everything you want to do with motion layout in jetpack compose then you should watch this video till the end so you could imagine that this is some kind of scroll effect here like a collapsing toolbar just for simplicity i'm using a slider here um but i will basically show you how motion layout for jetpack compose works because that was integrated with the last um constrained layout compose dependency release like once that got stable that dependency there's now also support for motion layout and it's awesome like i really enjoy using it it seems very stable even though they um they said it's still experimental but we can make pretty cool things with it in a pretty easy way um it's of course not very beautiful here but i want to show you how you can make these move effects um that it transitions here in a little arc and that the color changes those are just typical things you want to do with motion layout so let's jump right into android studio you create a new project here and the first thing you want to do is you want to include this constraint layout compose dependency version 1.0.0 that includes motion layout motion layout which uh of course also exists for xml is in the end a constraint layout so what we basically do is the idea behind motion layout is we define a start and end state so the start state would be this and for that we have these constrained sets so we basically just have constraints where we say okay this image is constrained to the top to the bottom and to the left and then this text is just constrained to the end of this image and also to the top and bottom here that's our start constraint set so that is where our transition starts and then we define another of this set for the end state so here these constraints suddenly change here for example the um profile picture is now centered so it's not it's it's not left aligned anymore it's centered and the text actually is below our profile picture and if we just provide the start and end constraint set to motion layout then motion layout will figure out a way to transition our composables in this case um between the between that given a specific progress value here which we get from this slider so let's actually jump right into it it's really not difficult i really want to make the same section here just as an example you can of course make so much more cool stuff with motion layout and for that i will have a composable which i will call profile header and first of all well what do we need let's just create a motion layout here you can see there are different overloads we can pick for that one takes a motion scene and one takes a start and end constraint set so right now we can define constraint sets in compose directly so in kotlin if you've watched my constraint layout tutorial in my compose basics playlist you will know how this works it's not difficult it's cool however for our purpose here we're not going to do this we're actually going to pick this motion scene the difference is that for the motion scene we kind of define all of our all of our different constraint sets all of the transition properties basically what we want to animate how we want to animate it we define that in a separate json5 file so json5 is just a new type of json that's a little bit different for syntax wise but not really difficult and we just defined it in a separate file basically which views are of which composables are constrained to which other composers are too parent whatever and then we also define hey please animate the x rotation from this to this you will see how this works but that's basically the motion scene a file in which we define this so let's pick this and well right now we don't really have a motion scene so i would suggest we actually start with that so before we can actually go on here in our compose code we want to go to res right click new android resource directory because i'd like to put this motion scene in our raw file a raw folder this one here so we want to create this folder and inside of this raw folder we right click again create a new file and call this motion underscore scene.json5 and in here we are now going to define this motion scene from scratch because i think it's very helpful to just go through this process once to define this and then after that once you understood it you can just copy and paste it from your other projects and just adjust what you need but i think it makes sense to just go through this from scratch here so the first thing we do is we just create a normal json object here so just opening and closing curly braces now as i said we need to define our constrained sets that's nothing else than what we also did in xml with constraint layout just that we don't have a visual editor here we just specify hey we have these types of composables and here are the constraints that's really all we define in here so we have constrained sets here you can see that's a little bit different here than with a normal json in normal json syntax we would have quotation marks here in json5 we don't have that then in here we have basically two different constraint sets here on the one hand we have our start constraint set so the set where our transition starts and then we have the end transition set so that motion load actually knows okay i will transition or i will animate between start and end so let's start with start and go in here now this block of code we basically just define the composables that we have in our start constraint set so if we take a look here what do we have well on the one hand we have of course our profile picture that we need to set constraints for then we have our text here and we actually also have this background so most this is not the the background of motion layout that's important because the background is also animated so the background of motion layout is actually not visible here that would be this big thing and that doesn't change in size so if we want to actually animate the background then we need to make it a separate composable which is just a box here so we have three composables that we need to define constraints here for let's start with our profile pic and here we can just give it a our own id so that's going to be the id that we are going to also mention in code then to refer to that and we can simply open this and now just define the typical things we would like to define with constraint layout such as the width and height so let's actually say our profile picture starts at width 40 and height 40 as well so that would be actually this one here so it's just a square and rather small now we need to define the constraints so where this actually sticks to and i assume you know constraint layout here otherwise please watch my constraint layout videos first because yeah i think explaining that here would be the wrong place in the end we have of course four directions we could constrain a composable too so we have a top start and and bottom for the proper picture here all we really need is we need to constrain it to the start and the top and to the bottom we just add a little bit of margin here but we don't need to set a constraint for that so we have start constraint and here we define that actually as oops as a list so what we basically say is we say okay we constrain the start of the profile picture to the parent start so that's basically what we say we constrain the start of profile picture to the start of our parent and then we could have one more parameter which is a six in here which would just define the margin to the start of the parent so that's how you have to understand this we do the same for the top constraint which we would then constrain to the parent top in this case and also give it a little bit of margin here and that's already it for the constraints for at least the starting constraints for our profile picture the next ones is uh other constraints for a username so just the the text composable that we will use let's define another constraint set here so now we basically define how the username is now constrained and in the end the username start is constrained to the end of our profile picture and the top and bottom are constrained to the top and bottom of our profile pictures so we just center it vertically and that's what we will define here we're not going to give it a width and height because then if we don't do this it will just um yeah wrap its content which we want for the text so instead we're just going to say okay we have a top constraint which we're going to constrain to our profile picture and we don't need to add any margin here we have a bottom constraint which will go to the profile pic bottom and we're going to have a start constraint for our username which will go to the end of our profile pic and here we want to have a little bit of margin 16dp again so that we have that little gap here and then we're now going to have one last composable which is for the box for background for the dark gray background color here which will then yeah just make sure it is just uh filling the space that it has so let's declare that here and here we want to specify width and a height but what do we actually pick because the box should actually only be as high as our other content and if you're familiar with constraint layout then there is something like fill to constraints like a property in xml that was when we set something to 0dp like the width or height just that it fills the space it has or the constraints actually occupy and that's what we want to use here as well and in this json way of specifying this if we want to if we if we want a composable to fill the space it has we use spread so we spread the width and we spread the height and then for the for all the constraints we can just con constrain these two our corresponding parent constraints so the start will be the parent start then let's duplicate that a little bit the end will be parent end the top one will be parent top and the bottom one will be parent bottom now for the bottom one i will actually add a negative margin of 60 dp which will be yeah which will make sure that we have this space down here which would otherwise look quite ugly so now that is it for our start constraint set so now we've defined how our composables are arranged at the start of the transition now we want to do the same for the end transition so we actually copy this start constraint set and append it here and simply call this end so of course we want to have the same composables in here the same ids just that we now want to change the values so to which values we want to animate these now well the profile pick of course should become larger when we animate it so this would now be the end state of our transition and here we now define okay that's the new size of our profile picture and motionlight will then animate in between these values i will use a width of 150 here a height as well and well the constraints will also change a little bit on the one hand the start constraint of the profile picture will stay at the parent start just without any margin because in the end we just want to center it now between like horizontally so we will make sure that we have an end constraint constrained to the parent end and the top one will remain at the parent top with a margin of 16dp that's fine then let's jump to the username and constrain so the top of the username should actually not be at the profile picture top anymore because then that would mean that the top side of a username would stick to the top of our profile picture but we want to stick it we want it to stick to the bottom here so we change this to bottom and we add a little bit of margin so we have this little space here and then the start constraint we have that let's specify the end constraint which would be to the parent end so here we also just want to make sure we center it horizontally and here we can remove the margin so start profile pick start actually actually no not profile pic parent start of course so just center horizontally and the top one will go to the profile picture bottom and finally the box constraints our dark gray box will actually stay exactly the same way because here we don't really transition to new values all we really want this box to do is it should just yeah just spread the height of our other composables which it already does now so now we successfully defined our start and our and constraint set however what we did not define yet is how we want this animation to happen so when do we actually want to animate which values that's what we didn't define right now it would only really animate the motion in between these if you want that then you then you're good then you don't need any further setup here but for example if you take a look here we also animate the color here as we actually slide and you can not only animate the color you can animate so many more values like the text size like the rotation you can add more scaling whatever you can make such cool animations with motion layout so of course i want to show you how you can do this so below this constraint sets block right here we will define another block of code and that will be called transitions and here in this transitions block we can define different types of transitions we want to have and we are just going to have a single transition here between our start and end point which i'll call default so this default transition will go from start to end and now when i think about it we should actually make sure to use these single quotes for this json file file i'm not sure if it accepts these uh double quotation marks but let's better be sure and uh hit ctrl r to find and replace we can make a little backslash and a single quote here i actually double quote so we want to replace the double quote with single quotes um or we no we don't even need this backslash okay so just we want to replace double quotes with single quotes say replace all there we go fix that one and then we can go back to our transitions block here so now we define that we want a transition from the start to the end constraint set then we can define something like a path motion arc without if you can basically say okay should this transition start vertically or horizontally so basically how this motion arc yeah is arranged so if you see um how this transition looks like when we slide here then it's it's it doesn't move in a straight line to the new destination it's actually an arc and that's what we define here so we say okay we wanted this to start horizontally so start horizontal and then we have one last very interesting property here that we need to define that we want to define and that's called keyframes so here we can now specify individual keyframes so basically at which portions of our transition we want which values to animate to what that's basically what we define here so we have a key attributes property in here in which we can now define these different attributes and how we want these to animate and change during our transition for specific composables let's do this step by step so this is actually not an object that's a list here and in this list we have objects so for every single kind of attribute we want to animate here for every single composer rather we want to specify how this will happen so the way this works is we specify a target which is a list in this list we specify the ids that are affected by these changes we describe here so for example for the profile picture what do we want to happen well here we can now actually define our keyframes we do this by saying frames and i will explain what this means and actually for the profile pic we don't want anything special to happen in our transition i still want to show you how this would work so here for the frames we basically pass a list and this list will contain numbers between 0 and and what this will do is it will say okay at 0 of our transition so at the very start we can now define more properties that define specific changes transformation values for our profile picture so we could for example say translation x is um actually also a list 50 0. so what this would mean is at zero percent of our transition at the very start we move our profile picture by 50 pixels to the right and then when we transition towards a hundred percent we also remove this translation again so we animate it towards the value zero so that's how you can actually extra animate properties uh during that transition and you cannot only have zero and a hundred here you could also say okay i have zero thirty 80 and 100 and then you could say okay when my transition starts it should be 50 uh 50 pixels in translation x then after 30 of our transition we want 90 pixels to have a translation x value then 120 and then back to zero so that would also work you can define a bunch of keyframes here i will actually um just leave that at zero and 100 here remove this and we will make use of this but not now i will get back to this keyframes property here because i will later show you a problem that we that we will face and then how we can use these keyframes to fix this problem so for now we're actually done with this motion scene file here and we can jump back to main activity where we can now refer to this since we put that in a raw resource file we need to of course get that as a string first of all here in our profile header we need the context for that which you can get with local context current and then we can say val motion scene is equal to remember we use our context resources open raw resource and we simply pass the raw id of our motion c and since we want that as a string we can say dot read bytes so we read all the bytes dot um decode to string actually let's form that a bit to make it more readable like this so that just gives us the motion scene so basically what we specify here in this file as a string it's just a little bit more beautiful than just putting the raw string in here we got syntax highlighting and all that stuff so now for the motion scene we can pass a motion scene and that takes the content of uh string so we can simply pass our motion scene here we also need to add an experimental annotation here so we can hit no can't hit control i'll probably we need to specify this first so let's see we need a bunch of more parameters on the one hand the progress well let's pass that actually as a parameter here and then i will explain what this does which is a float value the progress basically just defines the percentage value where we are currently adding our um animation basically just this what this slider does here we are at zero percent then like 10 20 50 100 that would be the progress which defines how yeah how the animation like the stage of the current animation i guess that would be clear and then what else do we need let's just attach a modifier here and make sure we fill the max width and let's try again hitting alt enter no still doesn't work i don't know why we hover over this yeah let's just add this annotation not sure why alt enter didn't work and in here we now specify our composables that we have the motion layout there is no specific order we need to use here um we can just first of all specify the box so i think yeah the order actually matters so the box is at the bottom um but let's make sure we actually give this box a modifier fill max width and let me format that a bit like this so we want to fill the whole width of ours of our motion layout we want to make sure to give the background color of our dark gray and well how do we now know how does this box know that it should actually that it is actually this one this composer here with this box id with these constraints well for that we have a modifier property which is layout id and here we can just specify this box id we specified in our motion scene it's really that easy then we have a profile picture composable next of which i simply added one of my pictures in my drawable folder feel free to add one of yours i also use mine so i will have an image composable the painter will be in a painter resource are the drawable picture i call it and i will vomit that a bit i won't give it a content description but i will give it a modifier because i want to clip it of course to a circle shape that clip circle shape i want to give that a little border that i used um so border let's set the width of the border to 2dp import ep i don't know why it oh no i wasn't pressing out that might be why okay with this 2dp color let's set it to color green now we will make sure this is animated later and the shape will be circle shape cool so and we of course also need to do the same as here that we say okay this image refers to the layout id profile pic and then one last thing is missing which is our text the text here is just my name your name whoever's name i will increase the font size to 24 sp import sp and we also want to give the modifier and make sure it has the layout id username and i would say we just try this out as it is now it won't be it won't look as my example we will set it up like that but i will show you how it would look right now so in here in our main activity we have a column we have our profile header we basically need a progress state so we can just save our progress by remember mutable state of zero f so initially we start at zero import that has it for our profile header and then let's have a little bit of spacing six so let's say 32 dp actually and then we have our slider we can use to change the progress so the value of that ladder will be progress and in on value change we say progress is equal to it and let's actually also give it a little bit of heading horizontal padding of 32 dp just like that nothing very special let's launch this here on my device and hopefully everything works hopefully the syntax of the motion scene is correct but we'll see there we go let's wait for this app to launch and okay i would need to change the text color but you can read it if we change this you can see it already animates and that already looks similar to what we had or what i had in my example so pretty cool however you might notice that the text is overlapping a little bit with our image here and that's something we would like to fix so how could we fix this well now our keyframes actually come into play so we could now say that during this transition we simply move our text a little bit to the right so increase the translation x of our text here for a few for like for portion of our transition and that's what we can do with keyframes and we of course also want to animate the color here just to show you how that would work so let's jump back to android studio going inside our home of our motion scene to our transitions block and here in this key attributes block we want to define that we don't want to do this for the proper picture because we want to we want this to happen for the user name so we specify another block we say target this time it's the oops single quotes this time it's the username and the frames will be um 0 50 and 100 and then for the translation x we specify 0 70 0. so what does that mean that means when the frame is at zero percent so at zero percent of our transition at the very start we don't have any x translation because that would simply not center the view it would then shift the view in x direction if we would start with that we don't want this then at fifty percent of our transition our translation x is at its maximum at 70 pixels basically and then towards a hundred percent we move back to zero pixels in translation so if we now actually relaunch this take a look then if we do this you can see it's overlapping a lot less so we could even increase this a little bit more um but you can see in the middle of the transition the text is moved 60 px 70 pixels to the right because we use this translation x property and then at a hundred percent it will then move back to zero pixels extra translation so that's pretty cool and we can do so much more cool stuff with this um with these keyframes so for example just to show you what's possible uh we could for example duplicate this and say we have rotations at and then we can rotate our view around the z axis in this case so for example we have 180 degrees here relaunch this go in here and if we now do this you can see our text is actually moving to 180 degrees and then is moving back to zero degrees of course that doesn't look good but just that you get an impression of what you can now do with these different values and there are actually so many more which they have on their github page for motion layouting compose so just go through these play around it's a lot of fun of course i'll remove this rotation here but how do we actually animate the color because there is no property here for the color instead what we need to do is we need to specify that as a custom property that means we do this here in the constraint sets we say custom and here we can now give that an id of for example background and we can just specify the or we're actually in the in the end constraint set so that would be the color of our border and text in the end state so when it's expanded then let's actually just pick white so we use the white color code we copy this go to the profile picture start constraint set and simply specify the starting color and i'll just use my green color code here and now how do we get this custom property well in mainactivity motion layout here we can simply get this as state so we have a val properties is equal to motion properties and the id is background because that's how we call this property and motion layout will now animate this color in between this green value and this white value here so pretty cool we can now use these properties and say okay our image has a green border right now but we want the border to be the color of properties um value color and here we again specify a background and actually i told you something wrong we don't want the id to be background here we want it to be profile pic of course so here we specify which properties do we want to get well we want to get the properties the custom properties of profile picture and then using these properties we can use the individual ids of the custom block here to get these specific values like here we use profile pic and here we use background and then we can copy this and actually do the same for our text color so go here say color is equal to this it doesn't matter that is this refers to the profile picture because the color is actually the same if we now relaunch this we should actually see the color to be animated you can see it starts at green and then transitions towards white so that's pretty cool and that's how you use motion layout for jetpack compose um was a quite detailed video longer than i expected but i think it's quite important to go through this in detail because motionlight is not an easy thing but you can make such cool effects with that and it's in a really early stage right now for compose so depending on when you watch this video things might change but the general idea behind that will always stay the same so if you want to make cool transitions definitely consider this it's great it's an amazing alternative to just manually transitioning all that so let me know down below if you used motion layout in your app before and if yes for what kind of transition that would be cool to know because i think we can give each other quite some inspiration in regards to what types of animations you use this for because you can become so creative with that so let us know down below in the comments give this video a like and yeah enjoy your day see you back in the next video bye bye
Info
Channel: Philipp Lackner
Views: 30,243
Rating: undefined out of 5
Keywords: android, tutorial, philip, philipp, filipp, filip, fillip, fillipp, phillipp, phillip, lackener, leckener, leckner, lackner, kotlin, mobile, motion layout, animation, complex, constraint layout, jetpack compose, transition, effect, collapsing toolbar
Id: 1g3SPJxk4wc
Channel Id: undefined
Length: 34min 18sec (2058 seconds)
Published: Sat Mar 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.