Constraint Layout with Jetpack Compose

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to go over how to use constraint layout using jetpack compose and if you've been around android development for any amount of time i'm sure you've used constraint layouts when you are building your layouts this was the recommended way by the android team to build especially complex layouts on android you know they recommended don't nest relative layouts don't nest linear layouts you should be using constraint layout because it is more performant while this is not the case with jetpack compose you actually do not need to use constraint layout if you have complex layouts rows columns boxes services all these things are perfectly fine it does not seem to affect performance in the same way that nesting relative layouts nesting linear layouts did using when using xml so just kind of if you want to know how to use constraint layout continue watching this video but know that it is not necessary to use constraint layout and actu it's actually kind of complicated i would say generally speaking rows and columns are far easier to use but if you want to build something complex where you have things arranged relative to one another then keep watching this video this is the one for you so specifically speaking what we're going to do is we're going to build a couple layouts they're going to be very simple layouts i'm going to show you probably four different examples so if this is our app here we have our kind of you know our search bar up here whoops that's not a useful search we have our search bar up here what i'm going to do is i'm going to show you four different ways to build this layout there's going to be a loading progress bar that sits kind of in different orientations and then it's going to have some text that's aligned down below it that's going to say loading so i'm going to show you how to you know align it from the top different amounts make sure to align it to the edges you know align it to the bottom basically all the standard constraint layout stuff that you would need to do with xml also obviously how to align these two relative to one another let's start by taking a look at the constraint layout section for the jetpack compose documentation so developer.android.com jetpack compose layout and then scrolling down to the constraint layout section so if i read this it says constraint layout can help place composables relative to others on the screen and it is an alternative to using multiple rows columns and stack elements stack is actually deprecated box is the replacement i believe or i'm not sure if it's the replacement but that but that's what i use if i want to overlay composables on top of one another you saw that in the previous video constraint layout is useful when implementing larger layouts when with more complicated alignment requirements so generally speaking you can probably accomplish whatever you need to accomplish with rows and columns and box but if it's something super complex then constraint layout might be what you're after notice this note here this is very important so note in the view system constraint layout was the recommended way to create large and complex layouts as a flat view hierarchy was better for performance than nesting views are so basically what that says is before we recommended using constraint layout instead of nesting relative layouts linear layouts that kind of stuff but it says however this is not a concern in compose which is able to efficiently handle deep layout hierarchies so i mentioned this at the beginning of the video i said that it's not necessary to use constraint layout rows columns boxes all these things are perfectly fine it's not going to affect performance like it would with xml but i'm going to go through some examples anyway because you might have some complex layouts and you don't know how to build them so i'll show you how to use constraint layout with compose so let's go into our circular indeterminate progress bar because this is where we're going to be doing all of the work basically in this video so i'm going to show you four examples like i said now i want to get rid of this row scenario that i have here so i'm cutting the circular progress bar and i'm going to paste it over the row because we're not going to use that row anymore we're going to use a constraint layout so we can create a constraint layout with jetpack compose like this and i'm going to add a simple modifier to this that just says fill maximum size so i'm adding a constraint layout and it's going to occupy the entire you know possible height and the entire possible width this is important if you want to center things obviously because if you center something and it's not occupying the entire width then it's not going to get centered so occupying the entire width is important now this is where it gets a little weird and i think constraint layout has a weird feel with jetpack compose but it will make sense by the end so the way that you do this is you declare variables and you kind of tie them to ids i guess you would say like previously in a relative layout or linear layer or constraint layout in an xml you'd give it an id and then that's how you align it to something else so this is how you give something an id i guess essentially with compose so i would say like value i could say value progress or progress bar even progress bar equals create ref so what that does is it creates an id essentially and you can create multiple ids with a different way to kind of initialize this so instead i'm going to use a bracket and do progress bar comma text and then say create refs so what that'll do is the same thing is create ref but it's going to create two ids progress bar and text are those two ids now i want to tie those ids to particular composables so for us one of those composables is the circular progress indicator so i'll come up here and i'll paste that in now i can kind of set an id by setting a modifier parameter so i'll say modifier dot constrain as and then i'm going to pass that progress bar i need a comma here because i added that other attribute so constrain as and then i want to open this up and i get access to a lambda into this kind of constrained scope now this constrain scope gives us access to a bunch of other stuff so i can do like top oh this is kind of giving me some weird uh alignment issues here let's uh let's bring this over here okay there i got it i just played around with it looks like that that's probably the best view i can offer you guys okay so modifier modifier.constrain as then you pass the progress bar or whatever id as an argument and now i can kind of add the constraints to this thing so if we look at the constrain scope so let's actually i'm going to hold down control and click on this and this will take me into constrain as now i want to look at this constrained scope so control and click on this there's a bunch of things that are available to me i have parents which would be the parent i can align it to the start the top the end absolute right basically what you can see here is all the stuff that would be typically associated with a constraint layout so if i go back the way i can constrain this then is say if i want to constrain the top of this i would say top dot link 2 and then i can link to something else in our case i want to link it to the parent so i would do parent dot top if i want to then link it or uh constrain the bottom i would do bottom link to parent dot bottom see now it's doing another weird alignment thing there i don't understand what's happening but there we go that looks better now start dot link two and do parent parent dot start and you can do bot or end dot link 2 and then parent dot end so essentially what that just did is that's like that's basically just adding a constraint to the top to the bottom to the start and to the end so that would align it directly in the center so now what about the text that text that i was talking about that's going to sit down below the progress bar how do we then align this below the progress bar so first we need a widget obviously just like with our circular progress indicator that was a widget so let's add one down below it so i'll create a text widget the text here will just say you know loading dot dot dot or whatever you want it to say i'll go to the next line and then the next attribute here will be the style i'm just gonna add some basic text styling to this so text style we'll do you know color equals color dot black we'll do font size equals text unit so text unit dot companion.sp and we'll just do you know 15 sp or something like that now i want to do the same thing i did up here with the progress indicator i want to do modifier constrain as and then pass the id in this case it will be text so coming up here let's do modifier or sorry coming down here let's do modifier dot constrain as text because that's that id now open this up and i have access to that constraint scope now so instead of aligning it to the parent or aligning the top to the parent i'm going to do top dot link 2 and then reference that other id so i would do progress bar dot bottom then i'm going to do start dot link to the parent dot start that'll center it or i'm going to work on centering it so end.link to parent dot end so it's going to be centered horizontally because i'm aligning it to the start and aligning it to the end and then the top is going to be aligned to the bottom of that progress bar so this will work this will give us our desired outcome so let's run this and take a look so there's the app running and you can see that loading animation in the middle our that loading progress bar you know that didn't really show for that long so let's actually go into the view model and i'm going to change this delay to like 10 000 milliseconds just so we have like a longer amount of time that we can take a look at it before it fades away so let's run that again and again take a look at our progress bar so there's the app launching and we should see our progress bar in the middle there it is progress bar and then loading notice it's centered starting from here and the bottom is here so that's the center position it's not centered from the top here because the parent starts here and it ends here so it gets centered between the top being here and the bottom being here so that's how you align things relative to one another using constraint layout and jetpack compose you just create references then you use the modifier constraint as constrain whatever id that is and then align it to either the parent or another one of the ids like we did with the progress bar and the text down here so that's fine but what if we wanted to align it kind of in a special position like say we wanted to draw an imaginary line right here and i wanted to align the progress bar to that imaginary line so this is actually really easy with jetpack compose and constraint layout you can create these imaginary guidelines and they can act as reference points that you can align to just like the parent like the parent has a top bottom start and you can create a guideline for top bottom start or end and put it pretty much anywhere so i'll create a new variable up here called a top guideline and set that equal to create guideline from top and notice all of the constructors here we have guideline from top guideline from bottom absolute left absolute right and so on and so on there's a bunch of guidelines so the one i want is guideline from top and it takes an argument that is the offset and the fraction there's actually a couple different constructors here it says multiple implementations i need i'm going to use the one that takes a fraction as input so what this means is i passed 0.3 as a float so i'm going to create a guideline that is 30 from the top of the screen so that's what we want right like i said we want a guideline that's about i don't know right around here so it would be that's about thirty percent from the top of this this would be like zero and then this would be a hundred percent so point three or thirty percent would be somewhere around here so now instead of aligning the top of the circular progress indicator to the parent top i'm going to align it to our top guideline so we've drawn this imaginary guideline and now i'm going to align it so because i have this guideline and i want it to be kind of aligned right up top to it i'm going to get rid of the bottom constraint that way the progress bar isn't going to get pulled downwards so let's run this and take a look so there's the app launching we expect to see our progress bar about oh it's actually quite a bit farther so it's thirty percent from here to here that's what that means where this would be zero and then down here would be a hundred so that's thirty percent downwards that's our guideline now just as another example say i wanted to you know align it to the bottom for some reason i can say align guideline from bottom i could say i don't know i want to be like 0.3 from the bottom sure let's do that and we'll we'll change this to bottom guideline so bottom guideline and then i'll do bottom dot link to that bottom guideline so now what it's going to do here i'll run this and what it's going to do is it's going to have that progress indicator 30 starting from the bottom so it's going to go up about 30 so there's the app launching and then there's that loading progress indicator now we're going to talk about something known as decoupling the constraints so this kind of pattern or technique that i'm going to show you that's available with constraintlayout is going to be good for if you have you know you want to show something different for portrait and then something different for landscape mode we can actually write some logic and we can check if the height is like less than or the width is less than 600 dp then we know that it's portrait if the width is greater than 600 dp then we know it's landscape and we can create different constraints for constraint layout given those different scenarios so what i want to do here is i want to be able to check the screen size and then you know change the parameters depending on the screen size just for the sake of an example say we wanted to use a different fraction depending on if they were in landscape or they were in portrait that's a simple example not really realistic probably but it's i think you'll get the idea so the first step here is we want to kind of you know abstract out the constraints so currently we're using constrain as and then defining the constraints in here you know constraint as and then defining the constraints we want to abstract those out so that depending on the screen size there would be different constraints so i'm going to create a function down at the bottom here and this isn't going to be a composable function it's just going to be a private function private function we'll call it my decoupled constraints constraints and it will take one variable as input this will be the vertical bias like i said we're going to assume that for a portrait we want something other than what we want for landscape it's a kind of a silly example but i think you'll get the idea now i want to return a constrained set and don't worry about what that is right now let's just write this out and i'm going to go over this when we finish it up so i want to return a constraint set object and inside of this constraint set scope i can define the constraints so essentially this kind of creates the same thing we have here so here we have the constrain scope and i have access to all of these constraint variables so that's what i've done here i've created this constraint set object and now i have access to the scope again so i can do value guideline and set that equal to create guideline from top guideline from top and i'll do that vertical bias as the variable because that's the thing that's going to be different depending on portrait or landscape now i want to do my progress bar variable so progress bar equals create reference 4 and then give this an id of progress bar so this is like in xml when you had find view by id or given id to something in xml that's pretty much what this is i'm saying create a reference for something and give it an id of progress bar so i want to do the same thing with the text so i can say text equals create reference 4 text so now i have two ids that are defined and i want to tie those to a different set different sets of constraints so i can say constrain constrain and i want to pass the reference so i'm talking about the progress bar id open this up and then define its constraints so i can just copy these from what we have up here that's actually bottom but whatever we'll copy that and i'll change it so this should be top and then align it to the top and then second we'll do constrain again reference that text open this up and this one i can copy it's going to be exactly the same so top start and end so now i've defined some constraints and tied them to particular ids so i'm sure you can probably infer what we're going to be doing we're going to be you know returning this constraint set and then accessing them based on their ids for the particular composables so there's our you know set of constraints now let's scroll up and continue on up here so now the question becomes how do we know if it's portrait or its landscape but we can use this with constraints composable this with constraints composable gives us access to things like the minimum height the minimum width basically just things that are present on the screen like screen properties i guess you could say so first of all i want to say modifier equals modifier dot fill maximum size we always want to fill the maximum size like i said because otherwise centering things is going to look really dumb in a constraint layout it's basically not going to work now inside of this with constraints composable i have something called a with constraint scope and if i click on this so control click on this and go into this with constraint scope it gives me access to minimum width maximum width minimum height maximum height so these are all calculated based on the screen size so now i can write logic based on those things so you know i'll actually do whoops i'll do value equals constraints and set that equal to this if statement and inside this if statement i'll say minimum height which is accessible now inside of this width constraints scope that we have if this is less than 600 dp that means we're in portrait mode so i'll write a little comment here that just says we are in portrait mode so in that case i want to call my decoupled constraints and i can pass a vertical bias of 0.3 so that's like what we had before if you come down here that's what we have right we have our 0.3 vertical bias although this is a guideline from the bottom now it's going to be from the top so when we get that then we can do an else case and do my decoupled constraints and you know just for the sake of doing something different we can say if it's landscape mode then we want to do a vertical bias of 0.7 oops i have an extra equal sign up here so those will define our constraints so pretty handy stuff so now i have this constraints variable and i can use it for my different composables so let's go into our constraint layout now i'm going to cut this so cut this entire constraint layout and get rid of this white space and i'm going to put it inside of this with constraints composable so i pasted that inside of the with constraints composable because now i can use these constraints so this becomes very simple we don't need any of this stuff we don't need the constraint as modifier so i can get rid of that we do still need a modifier so modifier equals modifier dot layout id whoops layout id and then i can reference the string that defines that layout id and for us for the progress bar that means progress bar so if you recall down below in our my decoupled constraints function i created a reference or created constraints for the id of progress bar so that's what i'm that's what i'm accessing right here i'm saying modifier layout id and i'm referencing that progress bar so then it will find the constraints so i can do the same thing with the text so i'm going to copy this modifier come into here and just paste over the current modifier and then of course change this to text because that was the id that was used down here so it's pretty cool you know obviously it definitely cleans up what we were doing in here i mean i don't know arguably not also because you have this extra stuff you have to use with constraints but if you have something or different layouts that you want to use for different um screen sizes then i guess this makes sense i just realized also i forgot something we have to pass the this constraints variable to the constraint layout so constraint layout and do constraint set equals constraints that will make the you know the progress bar and the text layout id accessible so yeah like i said um it definitely doesn't really save on overhead i wouldn't say but if you have a complex layout and you want to adjust things for portrait or landscape or do some other you know complicated thing then this might be the best way to do it for you and you can decouple the constraints from in the composable by building a function like this where you build an id to find some constraints for that id and then you can just reference that id inside of the constraint layout that you use whoops one last thing before we run it i made another mistake this should be minimum width so min width not min height if the minimum width is less than 600 dp that means we're portrait minimum height that does not make sense so let's uh let's now run this and take a look and see if we are getting the expected behavior we should see a different vertical bias for portrait mode as opposed to landscape mode so there is our portrait mode so that should be 30 from the top yes that looks about 30 from the top based on the top of this progress bar now let's rotate this and we'll do another search so if i click on soup there we go you can see the vertical bias is is clearly much larger this is about a point seven vertical bias so we see that our constraint layout is working correctly now we're going to go back to a very very simple implementation so i'm going to delete the my decoupled constraints i'm going to oh by the way i'll put a gist down below that contains all these examples if you want to just you know take a look at them later because this is not going to be in the source code so i just um i'm going to cut out the constraint layout there and just paste it up here get rid of the constraint set and i'm just going to go back to how we were doing this before so i'll say you know value progress bar equals create reference we just need one i'm going to delete this text we're not going to be using that and i can delete this this layout modifier let me actually cut this and i'm going to put it down below the color and i'm going to write constrain as constrain as and do progress bar open this up and then just apply some basic constraints so top link to parent dot top and then let's do start link to parent dot start and then and link to parent dot end just a simple example now i'm going to leave this in the source code even though it doesn't matter we could have used that row thing that we were doing originally i just want to leave some kind of a constraint layout example in the source code so we're going to use this kind of simple one and of course don't forget the guideline for the top so value top guide line equals create guideline from top and we'll do a bias of 30 and then we will align that to the top guideline so just do top link to that top guideline so running that let's take a look at the app here it is running and there's our progress bar kind of floating about 30 down so that's doing exactly what we want at this point and of course don't forget to go into your view model and change this back to like one one thousand milliseconds because otherwise you're going to be sitting there and waiting forever to get data from the api so that's it hopefully that was helpful that showed you kind of everything you need to know about jetpack compose and constraint layout basically the punch line in my opinion is you don't really need to use it and you should only use it very very sparingly if you have complex layouts that are crazy it just it just over complicates things in my opinion because it's not going to improve performance so why over complicate things rows columns boxes those are the things that you want to use before you go leave some new year's engagement today if i planned everything correctly today should be december 31st so this is um new year's eve i guess and since it's covid this is the covid special i know probably most people aren't going out because you're not allowed to go out or you probably shouldn't be going out because you spread that disease so sit at home relax go through my jetpack composed videos maybe head over to codingwithmitch.com register and watch one of my other courses i got all kinds of high quality courses if you scroll on down on the home page there's the jetpack compose one that you're watching right now there's that course we have mvi architecture if you've ever been curious about that we have my classic powerful android apps with jetpack architecture this shows you everything from well the focus on this one is pretty much database caching caching we get data from a real api we cache it we basically design an app to work when there's no network connection that is what this project is all about we have some ui testing another ui testing hilt which we actually went over in this course we got clean architecture this one's probably the best this is definitely the best course on my website if you are a professional or you are looking to get into the industry the skills that you learn in this course are absolutely fundamental this will give you a big edge in any job environments whether you're applying or you're already at a job and you want to just improve your skills this is a really really really high quality course it's hard your brain might explode while watching it but you will learn a lot you'll learn a lot of really really fundamental skills you know anything from getting data from the network caching data designing different layers abstracting out the different layers so you can write unit tests espresso tests so ui tests dagger navigation components everything it's beautiful definitely this is the best course on the website you
Info
Channel: CodingWithMitch
Views: 4,942
Rating: 4.9682541 out of 5
Keywords: jetpack compose constraint layout, constraint layout android, constraint layout jetpack compose, jetpack compose constraints, jetpack compose constraintset, jetpack compose constraint set, jetpack compose decouple constraints, how to use constraint layout with jetpack compose
Id: ENhtEcj6HHs
Channel Id: undefined
Length: 25min 1sec (1501 seconds)
Published: Thu Dec 31 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.