Android Jetpack Compose Course - 2h for Free App Developer Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up youtube this is denis panetta for tutorials.eu in this two hour course you are going to learn the basics of jetpack compose so of this android framework that has been released this year and it allows you to build beautiful applications using kotlin code only so you don't need to use xml code anymore you can just build the ui using kotlin and that's really cool it's a very different approach it's similar to what is being done in flutter so if you know dart and flutter already this will be very common to you but basically what you're doing is you are writing widgets that you then use as ui elements in your codes and it's a very cool thing it's called composables then and this video is just the beginning so if you really like this video you should hit the like button because once this video hits 500 likes we are going to upload another video which will be how to build the entire gmail ui using jetpack compose so if you want to learn that as well hit the like button and also subscribe to that channel if you don't want to miss out because we're going to upload that gmail video on that particular android specific channel so tutorials.u slash android and you can find the link in the description below to the channel as well as to the complete course because those two parts of the course are just going to be a small section of the entire course so if you want to learn everything that there is to know about jetpack compose definitely check out my jetpack compose master class and by the way if you don't know kotlin programming at all don't worry check out my android master class youtube video that i have uploaded it's a nine hour course where you learn the about the basics of kotlin programming in the first six hours or so of that youtube video so check those out because you need to understand the basics before being able to do anything that you're going to learn in this video all right so a bunch of things that you need to do now let's look at what we're going to build and in this video we are going to build this user interface that you can see here and along the way you are going to learn a lot about jetpack compose all right so you can see that we have a profile image here of a dog in particular and this is going to be a card in which we then have an image in which we have a bunch of texts and then we also have buttons and they are positioned accordingly so there's a lot to learn about rows columns as well as constrained layouts and how to use those not in xml but particularly in kotlin using composables and jetpack compose so the framework okay so i would say let's get started with the fundamentals i wish you all the best and by the way don't forget to hit that like button if you don't want to miss out and see the gmail video and subscribe to our tutorials you android channel if you want to see that video once it comes out let's jump into jetpack compose and see what it has to offer and what it even is so in the past couple of years developing native android applications has improved quite significantly ranging from architecture improvements to the tools and libraries that help in speeding up development but the way we create ui widgets and its interactions remains the same where we most times need to have a layout build with xml and then an activity or fragment that we have to write with either java or kotlin to interact with the user interface widgets in the layout the good news is all of this changes with the newest ui framework jetpack compose so jetpack compose is a declarative toolkit for creating high quality user interface components making it easier and faster to write beautiful applications with less code so there is no need for separate xml layouts or multiple activities so just one activity that will serve as an entry point into the api is required composable functions are capable of building maintaining and updating the user interface and since xml files are no longer required there's no need for find view by id view binding or data binding which each were quite complicated and cumbersome to a degree well find view bite it was quite simple but had its flaws by itself so all of those techniques they were there and they served their purpose but now it's time to have a better approach which is jetpack compose so jetpack compose is interoperable with the traditional way of developing android applications and can be added to already existing projects while you migrate gradually to using composables only it's just about a normal function with the add composable annotation so we have this function my app here where for example we have the greeting or we'll call the greeting function and pass welcome to tutorials eu and we're going to see how this actually works in an actual application we're going to build a bunch of composables we're going to use existing composables but also build many of them ourselves we're even going to go as far as to build entirely custom composables that are going to be quite advanced and complex but super powerful and not too difficult to understand because of the beauty of jetpack compose in general so let's go ahead and see this in action welcome back in this video we're going to create a new project which is going to be built using jetpack compose so here on the new project you can just select empty compose activity and it will generate the jetpack compose code for you so i'm going to call this application dog profile page and you can see that the package name is going to be eudotutorials.dog profile page i have the save location as well as something very interesting is that the language is set to kotlin and i cannot change it and that is because we're using jetpack compose and this is limited to kotlin and is not built for java then we have the minimum sdk of being api 21. so let's go ahead and create the project this will take a little while and once it's done the files will be ready but let's already look at our main activity dot kt so we have our main activity class which is inheriting from component activity and it has an on method as we would have even without jetpack compose just using the old-fashioned approach well we call the super method and then we set the content to use our dog profile page theme so let's not focus on this part for now however let's look a little further down we can see that we have composables here quick pause in this video you're learning something about app development and if you want to learn more about android jetpack compose specifically then you should definitely check out my android jetpack compose master class in which you are learning the fundamentals of jetpack compose but then also go into more advanced topics by building multiple applications for example we're going to build an entire news application from scratch which contains loading data from an api using retrofit then using core routines and the mvvm architecture in order to make it a really clean application and a lot more so it's a 16 hour long course where you get the code exercises quizzes and obviously also the q a support so whenever you have questions you can ask them and we're going to help you out so get the course down in the description you get a huge discount over 80 and i hope to see you in that course so now let's get back to the video so this main activity kt file not only has the main activity class in it but it also has a couple of composables in here in this case the greeting composable and the default preview so let's look at this greeting composable as you can see it contains a text composable text is a composable and can also be referred to as a ui element for any composable it must be referenced from another composable that is why the greeting function has the composable annotation so here this at composable is an annotation and if we get rid of it for example we will see that we get an error because this text here is also a composable so you cannot use composables inside of normal functions the functions themselves need to be composable as well the main activity also contains other built-in composables the set content for example so if we go up here this here is also a composable which declares the ui content to the activity the doc profile page theme which is created using the name given during the project creation with a theme attached at the end this is used to provide the look and feel of our application so you can go over to your projects now and open up ui theme and there you will find that you have the theme kt file in ui theme you cannot only see your theme kt file but you can also see the type the shapes and the colors these were also files automatically created for us we will be talking about theme in detail in later lectures every project needs an activity to serve as the entry point into the application which is why we have a manifest file where this activity is defined which is the entry point to our application so let's look at this file real quick we can see it is an xml file so it's using the xml language so to speak we have the manifest keyword and then inside of it we have the application so here are some parameters that are defined for our application and then we have the activity that is defined here and you can see it is the main activity that's the name of it and it is using a certain theme which is the dog profile page no action bar theme and you could jump over to it it's under your themes xml file if you wanted to know more about it so there are just two items in there which says the window action bar is false and window no title is set to true so it deactivates the action bar but it makes sure that no title is set to true okay so this themes xml file by the way is found under your resources values themes xml so there are even some more files that were automatically generated you can see there is this colors xml the strings xml which were created for us some drawable files as well as some mipmaps we're going to go over those and use those different files over the period of this course but now let's get back to our android manifest.xml so we have the intent filter which basically just handles which activities to open up and how to jump from one activity to another for example so what we're saying here is when we open up the application we want to use this activity because the action is the main action and then the category is that this is the launcher activity basically when we are launching our application it will launch this activity which will be our main activity and currently that obviously makes sense because we only have one activity but what if we have multiple screens in the future well then it would make sense to obviously know in which activity we want to get started with so if you have a login activity for example so a login screen and then you have a screen where you see the details for your particular user account that you're logged in it would make sense to see the login screen first before you can actually get to your data right because otherwise you could see the data of a user that is not you so that is definitely something you need to take into consideration when building applications and we are going to consider that obviously okay so that's the general structure of our application so we have our main activity which sets the content with composables we have a composable here at the bottom which says greeting and the text and then we have a preview of our application so we can see how this would look in the preview but therefore we need to at least build the application once so let's run it real quick and build it because otherwise the designer will not show us anything so here at the top you can see you can go to your code you can split the screen so you see the code and the designer or you can jump to the the designer only okay so we have this text which just says hello and name and then here we call this method greeting which says greeting with the name of android so it's going to show the text of hello android okay so once the application is installed we can see it here and it says hello android at the top left corner which is basically this text here so now please go ahead and replace this android with your own name so check this place hello and then your name okay i hope you tried it it should basically be in my case hello dennis so i'm calling this greeting composable function which is this greeting function right here and i'm passing the name which is a string called dennis to it and it's going to set this text composable to have the property of text say hello and dennis so let me rerun it real quick and you can see it says hello then is here and by the way you can also go to your designer and you can see how your application will look like here but as there is really not much happening in our application it just says hello android so this is the default preview that we get through this function right here which is using the preview annotation so this is our starting point and you're going to learn a lot more about what's up in this android manifest along the way you're going to learn how to use themes and how to create your own composables to change the user interface to your liking so that's it for this video see you in the next one welcome back in this video i would like to talk a little more about this preview here so what you can see is that if we go to our designer it says hello android and that is still the case even though here we said hello dennis or hello name as we had in our fun greeting here but this has the annotation of add preview and the add composable annotation so if we want to see the changes in our designer we also need to make the changes for our preview option down here so instead of saying greeting android we could say welcome to tutorials.eu and you can see that now the change is being made directly inside of my preview screen so that's something you have to consider when you now run the application it will however still say hello dennis so there we are it still says hello dennis so that's what you can basically do with your preview annotation here okay so the main point here was really to see that there is a difference between the preview to the actual project that we have so i want to show you something else and that is that this text here is in fact a composable because i just said that right but we didn't check it so how can we check whether this text is a composable well you can hold the ctrl key and click on text and then you will see that this is a function called text which has this ad composable annotation assigned to it which means that it is a composable function so now you also see that there are a bunch of different properties that can be changed for this text and we have changed the text property of this text composable so here you see we created a text object you could say because even though this is not a class it's a function but it's pretty much like an object and we set its property of text to hello name and name is just this variable here as we saw so now let's go ahead and create our own composable okay so let's use the add composable keyword and then create a function and i'm going to call this my app okay so this will just be a very simple composable that will itself use a composable inside of it which will be text so now we can define properties and you see there is one that is required so otherwise this text composable function will throw an error so it's not happy with not having a parameter so all of the other settings that you have here are not necessary you don't have to define them but the text needs to be defined okay so let's define the text property to have the value of welcome to this video for example and then in the default preview instead of using this doc profile page theme and stuff let's get rid of this and use my app instead like so so now we're using our composable that we created inside of our default preview and can run this so now we need to refresh this it will quickly render it again and you can see it says welcome to this video now as a little challenge i would recommend that you play around with this a little bit so go over to your text and see what could be interesting things that you can define so the color for example is unspecified the font size is unspecified so let's change the font size real quick therefore i'm going to add a comma i can add it at the end here and now access font you can see there are different options here i'm going to set the font size to let's say 30 dot sp therefore i need to import sp so hover over sp and either click on import here or alt shift enter this will add this import here at the top which is the compose ui unit sp sp stands for scalable pixel so it makes sure that the text is going to look similar on different device sizes okay so if we now rerun it we will see that the text should be bigger because i think by default yeah you see the text is now bigger because by default it had a lower number so it was a smaller value and it's not the defined so here font size unspecified there are no details here it doesn't say how large the default value is unfortunately but it's going to be smaller than 30 probably something around 20 or 22 is the default font size so now you could go ahead and change a bunch more settings here the font family the font style and so forth but for now what was important to display in this video is how to change the preview and how to work with composables and and the text composable welcome back in the next couple of videos we are going to build this a little profile page that you can see here so we called it simple dog profile application and that's exactly what it should be about creating simple dog profiles as you see here so while this might seem simple what we have here there's a lot going on and you are going to learn a lot about pre-built composable ui elements this will expose you to some basic composables as well as attributes so let's go back to our project and create a new file so inside of your doc profile page go ahead and create a new cotton class file and select file here and i'm going to call this one profile page make sure to use file and not class because i don't want to use a class here this should be really a simple file so let's go ahead and create our first composable function in here using the composable keyword composable like so therefore you see we need to import android x compose runtime composable and we haven't done that manually or i haven't this has been done for me by the ide android studio so i'm going to call this one profile page okay so this will contain my entire profile page so to speak and now what i want to have is a column therefore i can just go ahead and use the column in here this is another composer so let's import it and you can jump into it and you can see it has this add composable annotation so a column needs to be defined so you can see here i couldn't use the brackets i would have had to enter some details and you can jump in here and see we would have had to add the modifier vertical arrangement and so forth but what we're going to do instead is we're going to use the curly brackets this will give us the column scope and this column composable is used for vertical placing of other ui elements so putting them together it is one of the layout composables that allows you to place items within it so let's add an image inside this column okay so now i would like to add an image to our my project and therefore i can go over to the resource manager click on this plus and import drawables and then i just need to go over to the folder where i have my drawable and i'm just going to enter the path here and select the husky so there is my image i'm going to click next and import this image so now it will be available in my drawables okay now that i have the image ready let's go ahead and actually use it in my column so inside of my profile page therefore we can use the image composable so the image needs a couple of parameters we need to import image as well and here we're going to use the compose ui graphics here and it's this one this compose foundation image we need to define the painter and i'm going to define the painter resource which has the id of r.drawable dot husky okay so this was the name of the file in my resource manager you see it has this name husky and it's inside of my resources so you can go over to your project and then go to resources this is the r this grader r dot folder called drawable and there is this husky jpeg that was added okay so that's how you can find the path here and now that we have the painter i'm going to define the content description as well so content description will be husky like so and you see now my image is happy i don't get the error anymore and i'm pretty much content with what i have so the image composable is used for displaying pictures and it accepts two compulsory parameters painter and content description so painter requires the painter resource which can just be a drawable with the id as we've seen and then we need to editor the content description which accepts a string or null okay so we wouldn't have to enter something specifically we could have passed null as well to preview the elements we just added we need a preview function so let's add one below our profile page function so here can you recall how the preview function would look like well we can just learn from our main activity so we needed this preview annotation and the composable annotation so let's go over here and let's add this preview annotation as well as the add composable and then create a function called profile page preview like so and now let's just call our profile page function which is this one that we've just created now in the designer or in the split view we need to build and refresh and this will then allow us to see our husky inside of our designer here and there we are we have our little husky so now let's add two text elements underneath this image because we use this column it can contain multiple different items in it so let's go ahead and just add a text composable with a text property of siberian husky all right let me add the text here which is our compose one so again the compose material text here and now let's add another text this one will have the text of germany okay so let's say it sits in germany this little husky okay let's refresh this page and we should see the image and underneath we should then see our text so you can see here siberian husky germany now unfortunately the background is gray so how can we change that well actually we just need to add this show background through so you see the background is white we can get that by adding this to our preview annotation as well so now you can see but once it is added that the background is white now okay so now let's go over to our main activity and get rid of this entire stuff that we had so the greeting the my app and instead of calling greeting here let's call our profile page that we just created and let's run our application to see if it's going to display accordingly onto our emulator so now we should see our husky you see the text as well here siberian husky from germany okay so you see it's not perfect yet the image really just doesn't use the entire available space and so forth so there are a bunch of things that we can still improve but that's something that we are going to see in the next video so we're going to decorate the screen welcome back in the last video we ended up with this result that we have right here and as you might recall this is what we want to get so we need to change the size of the image we want to get this circle around it and then you can also see that here at the bottom we have a couple of different details that we want to display as well so let's implement all of that and first of all we're going to look at modifiers because i want to modify this image here all right let's go over to our project and therefore if we look at our image and that is the profile page kt file if you recall and here we had this image which is this composable that we're using so we are setting the painter property we are sending setting the content description but then there is also something called modifier okay so let's add the modifier in here muddy fire and it's like this modifier and we need to use the modifier class here and there are a couple of settings that we can set or a bunch of functions that we can use for example we can set the size and you can see we can either set the size with density pixels the width and height within 60 pixels and so forth so there are different options what i'm going to do is i'm going to set this to have a size of 100 dp therefore i need to import the dp as well as modifier namespaces and i'm going to use the compose ui option here and then let's import size as well okay now you can see we have foundation layout size we have the ui modifier as well as unit dp added to our namespaces up there so now this modifier can have multiple settings so i have set the size i can now also clip it at the same time so i can clip the shape now i need to pass in a shape so let's import clip here and then there is this shape called circle shape so this one right here which is also inside of android x compose foundation shape okay so now the image will get a circle shape will have a size of 100 density pixels and i would like to also add a little red circle around it as you can see here so we have this little red circle around the husky before we do that let's quickly look at what we get at this point because the image should already be changed quite significantly here we can see that the image is now circled so to speak right now we need to still make a couple of changes so first of all i'm going to add a border here okay so this is the red border that i want to have and it's going to have a width of two density pixels and therefore we need to import border once again and then use two dot dp to get the two density pixels and then i think it makes sense to put this in the second line so it's a little more readable so we have the width then we're going to set the color and i want the color to be red so we can just use color dot and then the different colors are available or made available to us and i'm just going to use red here and finally i'm going to set the shape to be a circle shape so this should be using a circle shape as well so the border itself should also be a circle shape so here we just clipped it so we cut it so to speak and here we are adding the border with a particular shape so if we run this we will see that now our husky has a red circle around it so this image even though it's quite small so you could of course if you wanted to change that to 200 db to make this image a little bigger there so now this image is almost taking the desired shape but there is still one more fix as the left and right parts of the images if you look at it are not fitted in so they're not fitted in properly and to change that we need to add a content scale property to the image okay so there is this additional property you see we had the painter with the content description the modifier but then there is another one and the one and let me put that correctly in here like so actually we can put the comma directly after the last statement and now we can add the content scale property okay i'm going to set that to content scale dot crop you see there is this ui layout content scale from ui compose so again another compose item this one here okay now we should crop it properly so the image will now be cropped in you see now we see our beautiful little husky with the red circle around him so i would like to align this image as well because currently it's aligned towards the top left corner but i would like to align it towards the center and in order to do that i can align the entire column because if you recall this is inside of a column so this entire thing our entire code here is inside of the column but how do i now go ahead and add properties to the column because there are no brackets around the column well the curly ones but not the circle ones so we can change that by adding circle brackets here and it will still work the same so now we can just go ahead and add the properties that we want to change for our column and the one that i want to change is going to be the horizontal alignment so i'm going to set the alignment to be centered horizontally so that's going to be one of the settings that i'm going to use but then i'm going to set another one for my column and that will be that the modifier will make sure that we are filling the maximum size which means we're going to take the space that is available for us and not just as it's currently so fill max size and here this will now fill the entire available size for the screen so basically it's going to say okay for this dog take the entire width that you have available and then center the dog in the middle or put the dog into the center okay so we are talking about columns here right so a column well we have one column so far and we're going to see how we can later on use rows as well but currently we have one column where items are put on top of each other so now if you run this again we should see that the dog is now centered so we achieved this by aligning it towards the center and making sure that we are taking the entire width available okay so i just talked about rows and columns right because this is inside of column but now let's look at rows specifically so we can go ahead and put multiple columns into a row and this will make sense specifically if we want to achieve this behavior here so you see we have column 1 column two and column three so we have three columns here whereas this is in row one so this 150 is in row one and followers is in row two and this year as well row one is one hundred and following is in row two so if we want to achieve that we need to use rows with columns so let's put it underneath our image because it's still inside of that one column so we just have one column the entire width of the screen so to speak and now we can create a row in it so there is this row composable you need to import that as well it's this row here and now we can go ahead and add columns in there once again and these columns they will align towards the center as well so i'm going to use the same setting that i had here with horizontal alignment like so okay so let me copy it from here copy paste in there okay so now this column will be aligned towards the center and in there i would like to have a text property which has the value for the text of 150 for example and you see if you look at it the font here is bold so the font weight is bold this is thick here and this one is not bold so followers is not bold but the 150 is bold so how can we make it bold well we looked at properties before right so there's this font weight property and we can just go ahead and use font weight dot bold for this okay so now this will make the text bold and now we will have another text in here and this will be our followers so we're just going to say followers like so in here and now i'm not very happy with the positioning of this one so this should be better and now what we want to have is multiple columns inside of this row and now if we check this out we need to run so we need to rebuild unfortunately we cannot just apply the changes with a hot restart and we'll see this is what we get so 150 followers then siberian husky germany and i think actually this role should be underneath the text so let's see yes so let's just drag this row from here underneath the two texts that we had that will do the trick basically that's pretty cool so let's rerun this and there we see siberian husky germany and 150 followers so this is the second row that we created so far this doesn't really make sense unless we have multiple columns obviously so let's go ahead and create multiple columns therefore i'm just going to copy and paste this here and we'll make a couple of changes to it so this one was 100 for example and it was following not followers and this one was posts okay so how many posts does our doggo have is 30. so let's rerun this well you see we get the error here so if you get this error this probably has to do with you not re-running it properly but doing the hot refresh and you see there we have our followers following and posts but they are pretty close together very narrow so if you want to have a little bit of a distance what you would do is you would say that this row where they are in should take the entire available space so let's do that let's add a property to our row here where we can say that it should take the entire available with so it should be aligned where the arrangement is spaced evenly so they are apart from each other evenly therefore we can use the horizontal arrangement so horizontal and actually it's not very happy with my row here let me put it like this horizontal arrangement where the arrangement is spaced evenly so you can try the different settings and see how it will affect your application and then i'm going to add a modifier here so modifier which will make sure that i'm filling the maximum width so the entire available width and here not maximum size but okay so the row shouldn't take the entire space towards the bottom as well but only towards the right and left hand side okay so that's why we use with a nut size so let's rerun this and see how this is going to pan out and you see now they are evenly distanced to each other so now if you want to have a little bit of a distance towards the top here as well you can add a little bit of padding so you can just do that with your modifier property so you see we are changing the modifier and you can just add settings by using the dot here so dots and then for example adding padding of let's say 16 density pixels which is the default padding setting that you would use in an android application so let's rerun this and see there we are we have a little bit of distance and this looks a lot more evenly spent and it's a good start now seeing how our code is here we are basically copying pasting code all the time right so we have this column then we have two texts in there the same story here the same story here so we are copying pasting code if you are copying pasting code then you maybe should consider putting it into a separate function so let's go ahead and do just that so therefore i'm going to create this function called profile stats because we just have this fun profile stats that will hold this the statistics or the values of our items so you see what is important okay so what could we extract from each of those columns well what we just need to modify is basically those two texts so the amount of followers or following or posts so it's a count a value a number so to speak and then the actual title of the text okay so let's just extract exactly that so here i'm going to get the count which is of type string and then i'm going to get the title which is also going to be of type string so how can we now position it in there actually we can just copy or cut this column out there and then replace the settings so here this will obviously be the count and this will be the title so everything else can stay the same now we do have a little problem you see we get an error here do you recall why this could be well it's because we don't have this at composable annotation so let's add the annotation and this will fix the problem so now we can use the profile stats in here multiple times so let's just call this method three times once with the count and followers and this is obviously going to be a string as well as this one here as well then once again with and i think it was 150 right then once again with the 100 and following and make this a string and then finally we had the posts i think it was 30 so count of 30 and the title was posts all right and then we can get rid of those columns and now we just made our code a little cleaner because we extracted all of these composables or just this column including the two text composables into you a method or a function that we can now reuse so let's rerun this real quick to see if our application still works and you see it still works flawlessly okay so now if we look at this ui you see only the two buttons are still missing and that is something that we're going to implement in the next video because i think otherwise this video would be too long so see you there quick pause in this video you're learning something about app development and if you want to learn more about android jetpack compose specifically then you should definitely check out my android jetpack compose master class in which you are learning the fundamentals of jetpack compose but then also go into more advanced topics by building multiple applications for example we're going to build an entire news application from scratch which contains loading data from an api using retrofit then using co routines and the mvvm architecture in order to make it a really clean application and a lot more so it's a 16 hour long course where you get the code exercises quizzes and obviously also the q a support so whenever you have questions you can ask them and we're going to help you out so get the course down in the description you get a huge discount over 80 and i hope to see you in that course so now let's get back to the video welcome back in this video i would like to add those two buttons here at the bottom so the follow user button as well as the direct message button and they're not going to do anything as of now but i want to have them inside of my application so where would they be positioned well i would say underneath this row here where you see we have the profile stats so what do we need actually just another row okay so we need another row but this time with two buttons so let's add it to our application therefore we actually can copy from this row so let's copy all of this stuff here because i want to have the same settings i want to make sure that i have a little bit of distance towards the top and at the other sides i wanted buttons to be spaced evenly so i can just go ahead and copy the settings from this row here but now inside of the curly brackets i can go ahead and add the buttons that i want to have in there so let's go ahead and just add a button and you see this is the default settings that i get here a button which isn't composed material so let's just add this button so you see here we have this on click which is automatically created for us and with curly brackets so we could add whatever we wanted in here that should then be executed once we click on the button and currently we're not going to do anything but you see there is a to do here which lets us know hey there is still something to implement but now i want to define the button or modify the button so how do i modify the text of a button or add a text to a button well that's cool thing in compose you can just go ahead and use the text composable once again so what should be the text for it this one will be follow user and in this case follow dog and then i want to have another button just next to it and because we are inside of a row here they will be next to each other they will be arranged evenly spaced so what should be the text of the second button that one should say something like direct message okay so let's rerun our application and see how this is going to pan out and we see our follow user button here as well as direct message button and they also have this behavior of when we click on them that they create this little effect here okay and that's already it so that was a little introduction to how to add buttons and create another row where the buttons are next to each other and you see they're spaced evenly as we wanted them to be so we have a similar situation like we wanted to have in here but now you see that at the current state our husky is all the way at the top so we still need to make a couple of changes so we're going to look at cards and vertical scrolls in composables so see you in the next video welcome back in this video we are going to look at how to make this entire thing the content be inside of a card so if you look at this you can see that there is a little bit of an elevation here with a shadow so this is called a card so all of the other content is inside of this cart so let's go ahead and add that to our project and therefore we need to understand where all of our content is and it's inside of this profile page so basically what we want to do is we want to put everything that is inside of this column into the card so let's go ahead and cut it out and create this card and then put it into the card so i just pasted it back in there and now everything is inside of my card now i can style the card so i can add a couple of properties to it for example the elevation i already talked about it being this little shadow creating effect so to speak okay so it's elevated above whatever is underneath it and here i'm just going to use six density pixels that should be a fine enough value and then i'm going to set the modifier property with a couple of settings so first of all i want to fill the max size and then i want to make sure that the padding is good so here padding should be let's say towards the top i want to have 100 density pixels then towards the bottom also 100 density pixels and towards the left and right i would like to have 16 dp so start and end so start is a left and right is end okay so now i will have a padding towards the top the bottom the left and the right so right and left so let's rerun this and see if our application still works and we can see now we have this little cart that i was talking about but our content isn't positioned very nicely as of now so we need to make a couple of changes but before that i would like to make sure that it's rounded even though you see it is rounded by default but if you were to make the shape rounded yourself and you wanted to define the border manually you would go ahead and you would use the border method here where you can use different overloads you see here the border stroke overload with the shape or the one with the brush and shape or the one with the within color and shape so i'm going to use this one where i need to define the width in density pixels so i'm going to say i want to have a border of two density pixels and then i want to have a color and here you could go ahead and use any color you want so let's make it very obvious and use a black color for the border and then let's use the shape of rounded corner shape where you then need to define what the size should be and i'm going to use 30 percent for the corner to be rounded so let's check this out let's rerun this and we see this is what we get so we get this rounded corner shape with 30 percent and then this black border as well so this is this black here you can of course use white here as well and let me do that real quick we see that now we don't see it but it's going to be inside of it so that's the invisible border that we're going to use for now and now if we test our application and we turn the emulator around even though in my case the actual emulator is not turning but you see that the application itself and the android or s turned you can see that now suddenly all of the content that this is disappearing so we can only see the image we don't see much of the rest of the content so that's something that i would like to fix though and therefore i need to add something called vertical scrolling and i'm going to add that on the column level so i want the column to be scrollable the card itself doesn't have to be scrollable and the entire page doesn't have to be scrollable but the column itself this one here should be scrollable therefore we can add the modifier to it and that will be the modifier vertical state so here modifier dot vertical i think what your scroll it was yeah vertical scroll there we are and there are different scroll states that you can now pass okay and the one that i'm going to pass is the remember scroll state okay so this will make sure that it remembers the scroll state that we had and i need to add the comma here for this to still work now obviously this modifier here won't work anymore because we're not filling the max size anymore and then i would also like to add a vertical arrangement for this column so here vertical arrangement and this will use the arrangement dot center so i want to center my entire content of the column now you could go ahead and add comments here to indicate what this entire column is going to be about so this will be content of our card including dog image followers or description followers etc okay so now let's run this again and see how this is going to fare for us and we see now we can scroll inside of this little card unfortunately you can see that there is always this distance 100 density pixels which makes sense if we rotate for the phone the other way around so let me see there it makes sense to have this distance but in the other view it doesn't make sense so here like having this huge padding towards the top is too much you could also fix this by making sure that the application is not going to allow to rotate that's also fine in many cases so sometimes you don't even want to be well to allow the user to rotate the phone or to use your application in a rotated version and so forth so instagram for example doesn't allow that either all right so that's it for this video in the next one we're going to look at constraint layouts in jetpack compose welcome back so at this point we have this beautiful little card with our husky and all the items looking quite good the problem is that what we're using here are a bunch of columns with a bunch of rows and it can become quite complex when it comes to more complicated and advanced user interfaces so this is a rather simple one but sometimes things are just more complicated and in that case it really makes sense to use something called a constraint a layout which is also recommended by google as the way to build your user interfaces so in this video we are going to restructure this entire user interface using a constraint layout and that can help us place composables relative to others on the screen and it is really an alternative for our nested row and column box custom layout elements that we have used so far so constraint layouts are really helpful when it comes to larger layouts with complicated alignments so the steps that we need to take include creating a reference for each composable in a constraint layout so we need to have the name for example for this image here it has to have an id let's call it dog image for example then the text could be called breed this could for example be the location where the dock is or whatever okay so everything has to have a name and then we can find it and then we can use those modifiers to actually constrain them to other composables or elements so for example we know that dog image for example is above the breed okay and then at the same time we see that the dog is towards the top so it's the most top element that we have and then everything can be relative to each other so this element here with the text and the followers is next to this one so it's towards the left so towards the border of your screen and then or to the card specifically here and then to the right it has this element where it says 100 following and then to the right it has 3 30 posts and so forth right so we're going to set all of this up it sounds quite complicated and it really isn't too uncomplicated but we're going to be fine so let's just have a look at this the first thing that we will need to make sure is that we do have an implementation inside of our build.gradle app file so colon app here in the brackets is really important otherwise this won't work so here in the dependencies so you can scroll all the way down you will find dependencies down here here you are basically saying which kind of packages you want to be available for your project and the ones that we have by default is here for example compose ui and you see we're using compose ui then we have the material from compose we have the tooling preview so that we can preview our compose layout and so forth okay so now here we need to add the following line let me paste it in here it's going to be this android constraint layout colon constraint layout minus compose colon 1.0.0 minus rc01 this is going to be the version that i'm going to use here specifically and this will now allow us to use constraint layouts therefore we need to make sure to sync it so click on sync now otherwise this won't work obviously so now once the syncing is done we can go back to our profile page and now use constraint layouts inside of here okay so let's convert this entire page so the profile page to use instead of columns are constrained layouts now unfortunately if i do that then all of this other stuff will cause some errors for now but let's have a look so i'm going to con use constraint layout here okay so this one right here constraint layout now obviously i get some errors here because we need to as i said define the ids so for example the image needs to know what name it has and so forth so we need to create references and let's do that for every single composable so therefore inside of our constraint layout and as this constraint layout is not a column but it is something different we don't need to define properties in it so we can get rid of that you see now the arrows disappeared but this by itself will not fix our issues so we need to create a reference id for the image composable for example so we can just go ahead and create a value which will be of type image and we define it as create refs so we create the reference ids here so now we can add a reference to our image so you see we have this modifier for our image okay this modifier has size the clip the border and now we can add a constraint as so here constrain as and give it a name so i'm just going to constrain it as image when we use constrain as however we also need to define how something is positioned so for example the image is going to be connected towards the top okay so we use here top dot link to so we're linking it to an anchor and here we can just go to parent dot top so we're linking it to the top of the parent now it is linked to basically its parent which is the card itself where it is inside of so this image is inside of the constraint layout which is connected to the card which is now going towards the top and then we need to define that it will be at the link left side as well so we link it towards the left side of the parent so parent dot start so start is left the left side and end is the right side so n dot link to and here parent dot end okay now we need to define this modifier with those constraints for our text as well so for the siberian husky so modifier and i'm going to use muddy fire and this has to be separated by a comma okay so modifier dot and we can use the constraint as here as well so now we need to say what the reference name for this text will be so how are we going to call this text and i'm going to call this text name text and now i can connect it to my top of the bottom of the image so what is going on here let's have a look at this so what i'm saying here is the top of this name text so the siberian husky should be connected to the bottom of the image so it should be underneath the image and the image is this one here so now i can go ahead and also make sure that the left is linked to the left hand side of the screen by connecting it to the parent and the right is linked to the right hand side of the screen so parent and okay so now for us to test this let's comment everything else out all the way up to the bottom row okay so i'm going to comment all of those parts out and i still get an error so here now i have a reference to my image but i don't have a reference to my name text so i need to add that reference here as well so let me add the name text here as well and i realized that this should be called create refs like so and then the arrow will disappear as well so now let's run this real quick to see if our ui is still going to work at this point we should only get the image and the text so the name of the dog breed so there we are we have the image and we have the text okay but now we're using the approach that google wants us to use yeah all right so this is how we added the name text now as a little challenge for you can you add this text here so this text which says germany where the doc currently is situated or lives currently can you make sure that this will also be on the screen but will be underneath this text here which says siberian husky so you will need to create a modifier and you will need to change those things up just a tiny bit okay so please go ahead and try this for yourself all right i hope you tried it so i'm going to comment this in so comment this uncommented so to speak and then i will need to add the modifier in here and you know what i'm just going to copy this modifier here and just make sure that the name that i give this so the id so to speak for my location text will be different so i'm just going to call this one for example country text okay so this will be country text where is the dog so obviously the country text doesn't exist so we need to create the reference up here so let's add the reference country text now let's make sure that it will be underneath not the image but underneath the name text so here we can say that the top of this text here which says germany which has the name of country text or the id of country text should be at the bottom of the name text which means just underneath it so let's have a look at this let's see how this is going to pan out and there we are so we have the siberian husky and underneath we have germany so how do we now add the other ones so let's add the row for example here let's start with the first row before we add all of the other rows okay so inside of this row we have the profile stats which are linked together which is still okay so we can still use composables as we have done here where we use a column and it's connected but as you see we use a column and before that we use the column within a row within a column and that's really something you should try to avoid because all of this nesting of columns and rows to at the certain point is just becoming inefficient when it comes to performance so that's why we are even bothering to set up this constraint layout okay so this is really something you should take into consideration all right so now that we have this managed let's go ahead and add the row so we have a modifier for the row already so that's cool so now we can just add our constraint as and give it the name i'm going to call this one row stats and then i'm going to link it okay so top link to and here i can just go ahead and link it to the country text so country text like so and to its bottom to be more precise so i want this row to be underneath our country text and i want it to be called row stats and obviously i need to add the row stats to my references that we need to create okay so here at the beginning of the constraint layouts we have our image the name text the country text the row stats right now so let's check it out and see how this is going to pan out and we see we have our row with the followers following and posts okay so that seemed to work that's perfect so now we have our profile stats beautifully and you see we didn't have to add this that it's linked to the left or to the right we just say it's underneath the existing text and now you might think you could have gotten rid of these two other lines here as well but let's check it out let's see how this is going to work out and you see now germany is all the way to the left because we didn't say that it should be linked to the left and to the right because if we link it towards the left and to the right it will be dragged towards both directions which will end up pulling it directly into the center where we want it to be like we have it with the siberian husky okay so let me get rid of those two lines and run it again there we are so why do we not need it for the row well this row by default is going to fill the max width as we have defined it here okay so we defined that it should take the entire width possible so we don't need to define that it should be linked to the left and right all right now at the underneath of it we have our row with the buttons okay so now we don't need to put an extra row for the buttons what we can do is we can position the buttons directly so let me get rid of all of this unnecessary code but obviously we need to add modifiers to our buttons so the modifiers where would we put them well we put them at the bottom or button level at its parameters here so we are defining that we need a modifier here so let me put that in a second row or line modifier dot and here what we need to do is to use constrain s so do we have it directly here well you see there are so many different methods right so let's just tap it out constrain as there we are so now we need to give it a name so let's give this a name of button follow so this will be the follow button and obviously once we create this id we need to add it up here as well okay so let me put that in a second row for it to be still readable very well and then we can go ahead and define where this button should be and i'm going to say that it should be linked to the row stats dot bottom and then i can also directly define a margin for example so i want to have a little bit of a distance to it so i'm going to add a margin of 16 density pixels to it now this point it created a little bit too many brackets for me then i want to make sure that it is linked to the left hand side so link to the parents start and to the well the end will only work once we have the button that we want to have right next to it so let's run this real quick just to see without this button here let me cut it out for a second so you see this is where the follow user will be let's just add this additional button the second one and i'm just going to copy this part here and put it in here so this one will be the button message so let's rename it button message let's make sure to add it as well here to our references and now we can use the button message and i want it to be also underneath the row stats and i want it to not be at the parent start but towards the button follow so it its left side should be to the right of the button follow and this means that we need to say end so button follows end so it's right-hand side should be to the left-hand side of our button message that's what i'm defining here and at the same time it should be linked to the right-hand side of the entire screen or to its parent to be more precise so here i'm going to define it as the parent so let's see how this is going to pan out you see now the button is connected to was to the right of the follow user now let's also make sure that there is a relationship in both directions so i'm going to link this right hand side also to the button message how i call it right so to its left side so to its start which means we need to use the link to method so now the width is something that i'm going to define as well what i'm going to say the dimension should be wrap content so it should only be as wide this button as the content requires which this wrap content does for us so it's not going to be wider than it needs to be basically based on the text that we have inside of it okay so let's check it out and you see now our buttons are perfectly linked to each other because we have specifically set the constraints now but now we have one a little problem and that is our husky here at the top it's directly linked to the card so there's no more space at the top let's take care of that as well therefore we will need to use something called a and therefore we will need to use something called a guideline and guidelines are invisible lines for positioning elements to a particular point on the screen from different axes so now we want to create a guideline from the top let's go ahead and assign it therefore let me go up a little bit so here when i'm creating my reference i'm also going to create my guideline so guide align as i'm going to call it and this one will be called create guideline or we call the method guideline from top okay so here i'm creating a guideline of 0.3 f and i need to make sure that i'm not using capital l here so the method that was predefined so what this will do is it will create a distance of a third towards the top so it will go down a bit so now instead of making sure that my image is going to be here towards the top of the parent which is current currently the case you see it's directly connected to the parent i wanted to use the guideline so here i'm not going to say top but basically just to the guideline here so link to the guideline let's rerun this and see how this is going to pan out and you see now it created all of this distance for us so it's at the second third so to speak of the screen so that's how you can define the guideline so let's play around with this let's say we set this to 0.1 and now you see that there is significantly less of a distance so you could play around with this and see what fits your requirements okay and that's pretty much how we can rebuild our ui that we had built before in a constraint layout which as i said is the best practice approach and well now you know so the structure is always the same make sure that you create the references with the name that you then want to use in your constraint as as a parameter and then in curly brackets you do the linking to either the parent and start means left and means right top means at the top of obviously and bottom at the bottom of whatever you are linking it to so our image is now linked towards the guideline that we created which just pushes it a little further down it is linked to the left hand side and it is linked to the right hand side of its parent which is this card because if we look at it our constraint layout is inside of this card and it's going to be a little more obvious once i connect those two like so so now it's obvious it's a constraint layout is directly inside of the card which is inside of the profile page okay so that's it for this video in the next video we're going to look at how we can use constraint layouts with the coupled api so see you there welcome back in this video you are going to learn how to use the constraint layout with a decoupled api that can help us build different designs for the portrait and the landscape orientation so we are simply going to decouple the constraints from the layout they apply to by creating different constraint sets for each orientation so what does that even mean and why would you bother so the thing is we have our screen as it looks like this right now and if we want to rotate it or if the user wants to use it in landscape mode we want to see something like this where we have the image on the left hand side with the text of siberian husky in germany underneath it but then we have also the followers following in post in a different way okay so basically this is the design that i want to have in the end so of course you could say there should be less of a distance here at the bottom or something like that so that's really up to you or if you want to have some more space here at the bottom to then add more items later on that's good as well but the thing is we don't get this behavior as of now we have to define this specifically we need to specifically define where every single item needs to be for the portrait mode which we have defined in the last video as well as for the landscape mode which we are going to do in this video but therefore we will need to make a big change to our application to our code base so let's go ahead and change our code up quite a bit here therefore what we're going to start with is going to be something called a constraint set okay so i'm going to create this private function called portrait constraints okay so here i will pass in the margin that i want to use throughout the entire method okay you need you need to import dp here for it to work and it should return a constrained set so this method when it's called it will return a constraint set so let's go ahead and return a constraint set so constraint set this one here so now we need to say what we want to have in this constraint set so how do we want to constraint all of our items here so for example we have this constraint for our image and i'm going to close samsung text because it's going to constantly want something from me so here we have the constraint as with the image and the top link to start link two and end link two and this is linked to the guideline and so forth but now let's look at how we can set this up inside of our constraints set here therefore we need to have a reference to our image so let's give it a reference by calling the create ref 4 method and here we need to pass in the id that we want to use and i'm going to give it the id of image so now i can create a constraint for my image so here i pass in the image and i can define what i want to have so let me just copy the constraint that i have for my image from here like so copy it and paste it in here even though the guideline of course now does not exist i'm just going to well keep it simple and say that it should be linked to the parent top so now let's do the same thing for our next item on the list so what would be the next item well i'd say it's the name text so let's go ahead and create a reference for the name text like so and now we need to add the constraint for that name text so here name text should have the constraint and now let's see what constraints we have for the name text and it was this one here we called it name text so here you see modifier constraint as name text so let's just copy this part out and put it in here for the name text and now we need to do the same thing for all of the other items as well even though here we're just copy and pasting because we had the constraints set up for the portrait mode but now we want to have them for the landscape mode as well so let's first of all finish the portrait mode and then go over to the landscape mode so i'm just going to simplify this and set up all of the properties that we're going to need here so all of the variables the country text the row stats and i'm going to call them row stats like this button follow but message and guideline okay so now let's go ahead and create the constraints for them so we have the name text now let's go ahead and add the country text which will just be to the bottom of the name text so it's top the country texts top will be linked to the bottom of the name text so it will be underneath it it will be towards the left of the parent or its left will be at the left of the parent and the right will be at the right of the parent which will drag it so we will get it like so where the text is in the middle so that's what we get by dragging it towards both sides okay for the country text now let's add the row stats as well so where we have the stats in one row as well as the button to follow and here we have something let me see that we have the width as well yeah so basically we have the same approach only that the margin now will be defined as the margin that we are passing to the portray constraints method so this parameter that we have here will just be used here all right and now the same thing for the message button okay button message will be linked to the row stats bottom it will be to the right hand side of the button fellow so it's left will be to the right of the button follow okay so that's what we're saying and this right will be to the end of the screen so to the parent end to the right hand side of the screen and we're wrapping the content for the width so now if we do that we can go ahead and use this portrait constraint but therefore we need to make sure that our constraint layout will be inside of something called a box with constraints so let's create this box with constraints and now we can create the constraints in here so constraints which will be defined using an if statement so if the min width will be 600 density pixels so if the width of the screen that we have available will be 600 density pixels then please use my portrait constraints with a margin of 16 density pixels and then otherwise so in the else block set up the landscape mode so here to do call landscape constraints so we need to of course set up the landscape constraints method which will be pretty much the same thing as our trade constraints method but has different values assigned to it so different constraints so now we just need to tell our constraint layout that it should use this constraints variable so it should really modify its appearance based on the settings that we have defined so here con and i should call this one constraints like so then it makes sense so now if i use these constraints you see suddenly all of this stuff doesn't work anymore so create refs doesn't work anymore the image with its constraint as doesn't work anymore so we need to get rid of this stuff all together so let me delete this the same goes for this create references and guideline because we cannot use it anymore so let's do the same thing with our well for the text we don't need the modifier to define it here anymore the same goes here so let's get rid of this i think it even goes all the way up to here and the same goes for this modifier well actually only for the constraints because here we want to keep the rest as we had it and here we use the modifier only for constraints either so let's get rid of the entire modifier and same goes here even though i just realized that we will need to use the modifier to assign an id so now let's assign ids to each of those items okay so we have those ids that we have here you see create rev4 id for the image for the name text for the country text the row stats and so forth right so now we need to say that for example the the image here at the top will have that particular id so let's assign this id to it therefore i'm going to add the layout id here and this one will be the image then we need to add an id to my text so let's use the modifier dot layout id and call this one what do we call the name text i think name text and the same goes for this one here separate with a comma add the modifier and actually modifier should be the modifier as well as modifier should be the modifier here and this one will be the country text so now the row needs an id as well so let's add a layout id and i think we call it row stats row stats the button here modifier and not this but muddy fire like so with the modifier.layout id and this one was the follow button how do we call it button follow okay and here we need to do the same thing with button and what was it message so now obviously all of our constraint layout should be inside of this box with constraints so let's make sure that we add the closing bracket in here and now our constraint layout will use the box with constraints and after having done that just for testing purposes let's add this portrait constraints in here as well because otherwise this constraints would be empty and you cannot pass in an empty constraints setting for the constraint layout so we're just saying okay constraint layout please use the following settings the constraints set that we have created for you okay so you can see constraints is of type constraint set which is exactly what the constraints will return or will be of type because the portrait constraints method is returning a constraint set so we have set up all of this set items and now we can use it for our application so now currently because we don't have the other constraint set which would be the landscape constraint set this will not do anything for us so this will basically be the same thing as we had it before where the application is going to look the same no matter which way we are using it or which format we're using it so let me let's open up dex again to display this okay so there we are so we don't have this distance to the top we are going to fix that later but you see that this is currently what we're getting so it's not exactly the design that i showed you earlier it's still fine it should be okay but it's not really the design that i want to have so i would like to design it in a way where these parts here so the followers following in posts will be to the right hand side of the siberian husky so let's set this up now therefore we will need to create an extra method which will be similar to this portrait constraints so let's go ahead and set it up private fun and this one will be a landscape constraints which will use a margin of density pixels and it will return a constraint set so now let's return the constraint set once again set like so and now we need to say how this constraint set should look like therefore we will need to have the references to all of the items as well so let's get those references in there and now we can start defining how the constraint should look like so let's start with the constraint for our image okay so the image how do we want the image to be positioned so i want to link it to the parents top and then i want to have a little bit of a margin as well so i'm going to set the margin to be the margin and the start of it should be linked to the parent dot start with the margin being the margin that we defined up here okay so this margin this is what this margin here is okay so this is just the image for now we don't have any constraints for all of the other items so so let's look at how this is going to do do on our device so we turn it around and well it's not using this constraint set yet so let's set this up real quick and where would that be i hope you can figure it out it's this part here so let's use the landscape constraints again with a margin of 16 density pixels so now we're going to use this other constraints of this other setup that we have started but they haven't finished yet and for now we only have defined where the image should be positioned so let's turn around our device and you can see the image is positioned here and everything else is just crammed towards the top left side because it doesn't know where it has to be it doesn't have any constraints which is why we get this weird look in our application so we can't even see the name of the dog as well as the other buttons and so forth because they are all on top of each other all towards the left so let's fix that therefore let's go ahead and design how our landscape constraints should be looking so i'm going to add the constraint to the name text and i'm going to paste them in here and talk through what's up so the name text should be to the image says start so to the left hand side of the image and it should be underneath so it's top the name text top should be underneath the image so what i want with this is it should be at the left underneath of the image you will see how this is going to look like now let's do the same thing with the country text okay so the country text however should be underneath our name text so its top so its country text top should be at the bottom of the name text it should be to the left of the name text and to the right of the name text so this is a little confusing you might say but what this will do is it will just position it exactly underneath in a centered manner okay so this is what these two constraints will do for us so let's rerun this and see how this is actually going to do so let's turn it around and you see that we have the siberian husky and germany underneath our image so that seems to work now let's add the other constraints let's add the row constraint and i want the row to be linked to the image to the top of the image but also to the right of the image so the images end which is the image's right side should be the start of the left hand side of our row stats and our row stats you might recall is this entire row thingy that we set up here so the profile stats which are inside of this row which has three profile stats with the followers the following and posts okay so now i want also to link the end to the parent's end so i want to say go all the way to the end of the right hand side of the parent okay so it's right should be on the right of the screen so let's run this again and turn it around and we see now the posts seem to work fine so now we need to take care of the two buttons right so let's go ahead and add those constraints as well and the button follow should be so it's top so it's top corner or top edge should be linked to the bottom of the row stats so it should be underneath the row stats with a little bit of margin and its left hand side should be to the left hand side of the row stats and this right hand side should be at the left hand side of the bottom message so we don't have the button message yet let's set that up as well and its bottom should be linked to the country texts bottom so this country texts bottom so what what it will do is it will make sure that the button doesn't overlap okay now the button follow will only make sense if we also have the button message because they are both important here so let's look at the button message its top should be also to the bottom of the row stats as we had with our button follow then its start should be linked to the button follow so to the end of the button follow so it should be to the right of the button follow and its end should be linked to the parent end and then finally the bottom of the button should be linked to the country text bottom as well so let's rerun this and see this in action so let's turn it around and we see that we get our little husky we have our followers and then we have the follow user as well as direct message positioned in the format that i wanted it to be okay so now you could of course play around with the values here for your constraints for your landscape constraints setup so now you know how you can make sure to have different layouts or how to define those different layouts inside of your jetpack compose application so basically what you need to do is you need to set up the constraint sets you could have also done it of course directly here but i recommend to create extra methods decoupling it and then we have the box with constraints in which we can then use our constraint layout with the constraints that we had set up okay and this is because the min width of 600 is not given for our application if we turn it and then it goes into the landscape constraint mode and i know constraints are really a pain in the bot at least that's my opinion i'm not a big fan of it i would have preferred to use the column stuff but it's just not as performant which is why we just have to get used to it and use it and once you get the hang of it you are going to have no problems at all with it and one thing that i didn't mention that you of course also always need to set up are going to be the layout ids so you need to set up those ids to be exactly the same as we have set them up here so now of course you could say use the guideline here for the top link to for the image if you want to use it in the constraint mode okay so 0.3 or maybe 0.1 and this should look a little better i guess so let's run it and you see now we have this distance towards the top and 0.3 will give us significantly more distance towards the top like so and it will center our doggy all right so that's it for this video see you in the next one there are some kotlin concepts and styles used in compose that we need to talk about some we already discussed in the previous kotlin lectures but need to go over them again and others you might be hearing for the first time because jetpack composers built around kotlin specific styles we need to get familiar with so that we can easily understand the apis compose has available for us so default arguments are initial values given to a method parameters at the point of creation so for example the button composable is created with several parameters for which most of them have initial values or default arguments making it possible to call a button composable without needing to provide values for all of them so let's look at the use of button elements so the button composable requires on click and content arguments when we look back in the previous slide we see that both declarations had no assignment symbol that is this equal sign making it necessary to provide them when the method is called and others are optional depending on the requirements you have for the composable so you see here there are many that have an equal sign which means they have something defined to them by default all right another concept is higher order functions which are functions that accept order functions as an argument and compose uses them a lot let's look at this example with the code block we can directly add the function body with what should happen when the button is clicked and that is using a function as an argument which is possible with the help of lambda so we can also decide to create a normal function and then call it within the block itself so we have used trailing lambdas already in previous lectures they are a special syntax for calling higher order functions whose parameter is a lambda outside of parentheses so the row element requires a content parameter which is a lambda so this code works but can look better when placed outside of the parentheses this is an example of a trailing lambda which is outside the row parentheses and therefore the parentheses is removed this way it looks more concise and less cumbersome so let's compare that you see like this so we didn't need to define the content in the brackets and so forth so next are delegated properties these are variables declared with the by keyword and are usually associated with a state for example the name state is declared using the remember keyword and then it's used within the text field to track the value directly when it changes we will see more of this in coming lectures and then destructing data classes so destructing simply means creating multiple variables at once an example is when creating reference id in constraint layout as we have used before with create refs we can create different ids at a goal and use them as required so we don't need to set them up all one by one a very important additional aspect of what we need to look at are co routines which offer asynchronous programming support and can suspend execution without blocking the main thread and jetpack compose is a reactive ui framework and changes its state as the user interacts with it these states can require heavy processing and need to be performed without blocking the ui threat compose makes this easier by embracing co-routine at api level rather than using callbacks so let's look at an example here a snakebar function is a co-routine function and we can easily call the remember code routine scope and then launch a block for show snack bar so showing the snack bar we're going to learn more about all of the idiomatic kotlin codes in the coming lectures all right so this was a little overview slash introduction to newer topics just to give you a first look at them we are going to work with those in more depth obviously so see you in the next couple of videos quick pause in this video you're learning something about app development and if you want to learn more about android jetpack compose specifically then you should definitely check out my android jetpack compose master class in which you are learning the fundamentals of jetpack compose but then also go into more advanced topics by building multiple applications for example we're going to build an entire news application from scratch which contains loading data from an api using retrofit then using co routines and the mvvm architecture in order to make it a really clean application and a lot more so it's a 16 hour long course where you get the code exercises quizzes and obviously also the q a support so whenever you have questions you can ask them and we're going to help you out so get the course down in the description you get a huge discount over 80 and i hope to see you in that course so now let's get back to the video welcome back in this video i would like to teach you the concepts of state and recomposition so we're going to use something called a text field which allows us to enter user input and it is stateless and only displays whatever you tell it to display to make it stateful we need to make it own a piece of state that it can change over time so let's look at this in an example because out of these keywords they don't make sense without the proper example so here what i have is a new compose application the jetpack compose one you can see that here by having ui theme directly here and also it's a component activity okay so now inside of the greet method i'm not having a text but what i'm going to use instead is going to be a column therefore let's go ahead and add column here and the parentheses will be empty i'm not going to add anything for now but i will change that later and then i'm going to use a text field and this text field needs a value and it needs to have code that should be executed on every single time that the value has changed so when we're entering something this method here will be called even though it's not a method but this lambda here will be called so now what we can do is we can also add a little button here i'm going to add an on click to it which will be empty so nothing will happen and then i'm going to add an content for it as well which will just be a text that will say display okay nothing too fancy really just a small text here so if you run this we will see that it's not going to look great but yeah that's what we're getting so this is the text field so the text input field and this is the display button so let's center them therefore we can change the column properties here and in particular i'm going to use the horizontal alignment one so here horizontal alignment which will be using the alignment center horizontally setting and by the way if you were wondering or get any problems with the button make sure you that you have my imports because otherwise you might get into trouble using the wrong imports and then the button doesn't work as intended and then everything is confusing so if we rebuild we discover that our application so even if we rebuild this now with our horizontal alignment you can see it is horizontally aligned but it doesn't look great so if we build we discover that it still remains the same and this is because the composable does not really understand how to change to the alignment with no size given to it so let's give it a fill max width using the modifier so for the column itself we're going to add the modifier here modifier dot modifier or equals modifier dot and here i'm going to use fill max width so it should take the entire width available now if you run it again it will at least be in the center like so but now if you want to center it in the center of our screen and not just on the horizontal level we need to add the vertical arrangement as well so vertical arrangement will be arrangement center which is this option right here and centering it is not enough we also need to make sure that we fill the max height as well so now you could have used fill max size it would have done the same trick but you can see that you can combine them so max width as well as max height in one line so now we have it in the center and we can get started with it and in order to prove that fill max size works as well let's just test it we can see it works flawlessly as well that's because the column is taking the entire available width and height and then arranges our item centered on a vertical level as well as aligns it centered horizontally we can also make the ui a little better by adding a space in between the elements this can be done using a spacer spacer is also a composable so let's go ahead and just add a little text here which will say something like hello then we have the text field and maybe we want to have a little space in between by using the spacer we can achieve that where we just say how much distance we want to have so modifier dot height and then we can just say for example 20 density pixels is the distance that i would like to have and therefore we need to import density pixel all right so hover over it import it and then we should be good so now let's use this spacer as well after the text field so it's going to add the spacer between the text field and the button so let's run it again real quick so you can see this has nothing to do with state but i just wanted to make sure that we have a little application running that doesn't look too awful or it still looks awful but it's not too bad so now let's actually get to the state part where we're going to talk about the remember keyword and the mutable state so let's get into state and recomposition first let's try to get the value to display on the text element as it changes on the text field within the greeting block we create a remember variable of type immutable of string so let's do exactly that so here in the greeting method we have all of the column stuff and so forth but first i create this namestate by remember so we're using the by keyword and then the member berries so here remember and import remember as well so alt enter and then we need to create the mutable state off and in this case it will be an empty string so let me import mutable state off here as well and to use remember as a delegate we have to manually add these imports so in case this doesn't work properly run time remember it doesn't seem to be in here let me make sure that i have it so runtime dot get value and then runtime dot set value okay and now you see the errors disappeared but now we're using remember as a delegate so within the text field we can now pass the name state to value and then assign the string from on value change to it so what does that mean well here in text field you see we have this value and i'm going to assign a state to it so this will be a string but at the same time we're going to manage it as a state and then on value changed i want to make sure that the name state will be overwritten with it and what is it it's this it here it which we get from this lambda here so on value change we get the value that is currently inside of the text field as this it variable which we then can assign to our name state which is the string that we have set up here which is using the remembered keyword and has the mutable state off method and then i would like to use this namestate inside of this text hello so instead of saying hello i want to say hello namestate so whatever the current namestate is it should be overwritten there so let's run this real quick and see what's going to happen there so let me enter something you see hello dennis is displayed so the display button doesn't do anything but whatever we do here you see it's directly reflected inside of our text up there even though the text field itself is stateless but we assigned a state here assign the value name state to it so now what if we only want to display the changes in our string there or in our text here once we clicked on the button so first we need to declare a variable of type string just below the remember type so here so here var name is going to be an empty string for now and once we click on the button we are going to say that the name should be whatever the name state currently holds and then we just need to replace the name state here with the name so basically we're saying the name state should be constantly updated right it always knows what the current state of that text field is but only once we click on the button the name that we are displaying inside of the text itself should be whatever the name state is at that point so if we run this again and i enter dennis now and i click on display well nothing happens this is because even when name gets its value from name state it still does not change at runtime because itself so the name variable this one here has no state so the compose elements are rerun to update composition when data changes which is known as recomposition so when this happens composables regain its data only from a member value so we still need to make the name value to be a remember type with a mutable state so that the text element can receive its data when it changes so this basically just means that we need to make sure that this name here is going to have also this by remember keyword by remember and then it is a mutable state of so here or uses this mutable state off like so so now let's run it again and test this and click on display and you see now it has changed so now dennis or whatever i'm doing entering here you see will be displayed there because now our name is remembering whatever state it has and it changes whatever is looking at it so to speak okay so this text is looking at this name property and when the name property itself is being changed then this text knows i need to refresh my ui so to speak so now even though remember is saved in memory it does not survive configuration changes and if we now rotate the device the state will be lost and this doesn't work on my emulator here so i will need to show it on my real device so let me run it on my samsung and unfortunately there's something wrong with my emulator i don't know what's up i tried many different solutions i would probably have to use a different android studio version but i want to make sure that we are using all the same android studio version okay so there we are let me enter something here let me click display and then turn it and you see the data is lost so we don't see the name anymore it's just gone and this is something we can change by using the remember savable so var name by remember is what we use so far but there is also by remember saveable available and there are inputs but we're not going to require them for now so if we rerun this now and we check it again and not on this emulator but on that one here then we will see that the state will be saved even though we are rotating the screen so let me display this rotate the screen and you see hello dennis is still stored in here even though it's not stored in our other text field so in this text field you see name state is only remembering but name is remembering and saving so remember saveable saves the variable even though you're changing the configuration which means you're rotating your screen so that's really what you need to take away from this there is something called state and whenever you are working with state you need to use the remember keyword and the mutable state of variable even though the value is going to be empty at start we are overwriting it and our ui is updating based on changes which is really really cool so this allows us not to have to manually call those updates but they are done automatically so to speak when the data changes which is really powerful so that's it for this video see you welcome back in this video we will talk about state and composition in jetpack compose and these are very important concepts that we need to wrap our hand around because we're going to use it throughout the next applications and it's really important and this is something that from my understanding is not really used in the old school approach but it's really used in well one hand and jetpack composed but also in flutter and so forth so state in an application is any value that can change over time in jetpack compose there are apis that make working with state easier so let's take a look at how it works so if you are familiar with the xml based views compose works different with managing changes in value so it has to be notified when there is a change in state for example so for example when something changes you need to say this thing changed so please do something with it so looking at this text field when we start typing into it nothing happens and this is because it does not update itself by default when the value changes due to how composition and recomposition works in compose so let's understand what some key terms in the world of compose mean so first of all composition composition is a description of the ui built by jetpack compose when it executes composables then there is recomposition which is re-running composables to update the composition when data changes and then there is initial composition which is recreation of a composition by running composables the first time so to easy track and use a value within your composable ui you can use the mutable state off which is integrated with a compose runtime it is observable making it easier to get the changes in values so now to make sure composables are updated when its value changes we use the remember keyword to store the a value computed by remember is stored in the composition during initial composition and the stored value is returned during recomposition so remember can be used to store both mutable and immutable objects there are different ways you can declare a mutable state these declarations are equivalent and are provided as syntax sugar for different uses of state you should pick the one that produces the easiest to read code in the composable you're writing the by delegate syntax requires the following additional imports so import android x composer runtime getvalue and set value now to create a state that will update a composable ui when it changes we do the following so to make the text field show the entered values first we declare a remember mutable state of variable and then set it to value as well as to the on value change which updates the entered value we can also use this value as a logic in a statement and set it to other composables like a text element so if the value is not empty we set it to the text composable as we move along in the lectures we will see more use cases of state and how they change during recomposition but generally what you need to just understand and be fine with is that it's basically just storing a very variable and whenever this variable changes the ui gets updated so that's really the idea behind it because if for example you were working in old school android app development and then you created a list for example and then you would update the data you would have to notify the list that the data has changed and this is something you don't have to do if you are working with state if you're working with the remember keyword and this mutable state of and so forth okay so this might be quite advanced at this point but once you are using it and once you've used it a couple of times you will understand the value of it and well that's just how you have to handle things in jetpack compose so let's get over to where we are actually going to use this in the next couple of projects congratulations you're done with this video and with the basics of jetpack compose so now you know how to build a user interface using kotlin only so without having to touch xml at all well for the colors maybe but even that can be done with kotlin itself so what's left to do is to hit the like button and subscribe if you haven't done so already and also don't forget to subscribe to our android specific channel where you will learn all of the android app development stuff that you need to know and where i will also upload the gmail user interface application building so where we're going to build in two hours this beautiful gmail user interface that there is you are going to learn a lot more about jetpack composed there so definitely subscribe to the channel hit even the notification bell if you don't want to miss out because this is going to be an amazing video and you're going to learn so much stuff for free so definitely check that out and if you don't want to wait and if you don't want to wait because that video about the gmail thing you will only be uploaded once this video here hits 500 likes definitely check out the link in the description to get the entire course and there is a lot more than just the gmail app and this part of the video that you have seen already there is also the news app and a lot more about mbvm core routines retrofits all of the good stuff that you need to know in order to build real world applications using jetpack compose so this is i think the longest outro that i've done thanks a lot again for watching the video and see you in the next one
Info
Channel: tutorialsEU
Views: 3,000
Rating: undefined out of 5
Keywords: Tutorials, Tutorial, Programming, Course, Learn, Step by step, guide, development, programmer, video course, video tutorial, learn how to, how to, jetpack compose tutorial, jetpack compose, lackner, android jetpack compose course, kotlin, jetpack compose kotlin, android jetpack compose tutorial, jetpack compose crash course, android jetpack, jetpack compose android, android studio, android jetpack compose, phillipp, android app development, philipp lackner, stevdza san, freecodecamp
Id: UsoWVoXDJsE
Channel Id: undefined
Length: 123min 3sec (7383 seconds)
Published: Tue Dec 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.