RecyclerView and CardView for Jetpack Compose (LazyColumn and Card)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back to another part in my mvvm jetpack compose course for beginners in this part i'm going to show you the recyclerview equivalent for jetpack compose and also the cardview equivalent for jetpack compose so specifically what we're going to be doing is building out these cards so notice that these list items sit in the card they have kind of an elevation here they have an image they have a title and they have this little score for the recipe and if i scroll this is very much the same as the recyclerview it's exactly the same it might look a little laggy for you because it's uh it's on the emulator but on my real device if you run this on a real device it's very very smooth the first thing that we're going to be doing before we start building any composables is we need to get this default image into our project so here it is here's the default image it kind of just looks like an empty plate with a fork and a glass this is the image that's going to show when you know an image can't load or while an image is loading it's always important to have a default image so you can get this by going to the source code for this project go to you know pretty much any branch the master branch is fine go to app source main resource drawable and this this image is called empty underscore plate.png so you're going to want to right click on this save it to your computer somewhere once you have it on your computer somewhere go to android studio and you can either just drag it into the drawable folder right here or you can use the resource manager over here on the left just click on this plus icon go to import drawables find wherever that image is saved here it is for me empty plate dot png hit next and then import that image now that should be in your drawable folder so here there it is empty plate png there it is nice and small just 32 kilobytes very important to have a very slow very very small low resolution image you want to have it have it very small don't occupy lots of space otherwise your your views can lag or your list can lag all right so let's start building this composable that's that's going to look like this card so this is the composable that we want to build this this individual card with an image a title and then a score so this we want to reuse this over and over again in our recycler view basically think of like a view holder in recycler view the the layout for the view holder this is kind of what we're what we're aiming for here so go into presentation right click go to new package call this package components so i'm creating a package that i'm going to keep all of these kind of custom composables inside of so create a new kotlin file and call this recipe card and then create that file now minimize this and let's build out this composable so obviously we want to annotate this with at composable do fun we're calling it recipe card and the function arguments are going to be a recipe so it takes a recipe as input and it also takes a function as input an on click function or a function called on click and this is for you know what happens when we actually click on one of those recipes then we want to we want to execute that function i'm going to give you lots of room here to give you a better view so what uh what comes first well the card view equivalent for jetpack compose is actually a card so we just call it a card and we can now pass arguments to this card to kind of dictate the styling the first argument is the shape argument this determines the the how rounded the corners are we're going to use a material theme constants file to access a constant that defines you know some shapes now this is probably going to be a little confusing to you you know what is this material theme thing this is actually a constant file that contains a bunch of like styling constants so here if i type material theme we have colors we have shapes we have typography if i go into typography we have like body button caption h123 through six a bunch of different pre-built styling kind of styles i guess is the way to put it and then you have of course colors so if i went to colors and then you have like you know a bunch of different colors uh the takeaway here that i want you to know right now is that this is a pre-built sort of class which with a bunch of pre-built styles that you can use easily in your application and you can customize this and we're going to be customizing it later so we're not customizing it in this video we're just going to use the ones that are already available to us so later in this course we're going to be customizing this just know for now that it contains a bunch of kind of styles that you use in your app you know also actually just to show you um you know you don't have to use the material theme like i could have done you know if you look at the return type of this it's a corner based shape so you could just create a corner based shape here as a constructor the constructor takes a bunch of arguments the top left top right bottom right and bottom uh bottom left and it takes corner size objects so you could say you know top left corner size and then you just define what the size is going to be if i want it to be like 5dp that would mean that the the top left corner is rounded 5dp that that would be how you could do this and then i'll obviously specify the other ones but we're going to use the pre-built one that just comes with the material theme so we can use either small we have medium we have large and those are just pre-built kind of corner based shapes that you can reference it's just to make things more convenient so again we're going to be going over the theming stuff later in this course because we're going to be you know customizing that entire material theme the next argument will be the modifier so get the correct one we're going to want to get the android x compose ui modifier now add some padding we can add padding to the bottom set that equal to 60p get that import also do some padding to the top 60p and then go to the next one so fill max width remember we want this card to fill the the maximum width possible and then add a clickable attribute to this modifier and pass that on click function so we've theoretically we're going to have an onclick function that gets passed as an argument to the card and then through this clickable modifier it will execute that function when it gets clicked now the last attribute will be the elevation every card every good card has some elevation the amount of elevation we'll use i think we'll just do we'll do like 8 dp and i didn't choose these for any particular reason you know i was just playing around with it and i thought that that looked good so that's the the starting point for our card now now what do we want the layout of this card to look like well if we refer back to the finished version of the app we have uh you know an image at the top and then we have another row down here with two entries a title and a score so essentially here we have like a column the first item in the column is this right here this image then the second item in the column is this row right here with the title and the score so a pretty simple one to build we'll just open up a column here the first item inside of this column will be the image so you always want to check to see if the recipe actually has the thing that you're going to be using so we're going to check for that featured image just checking to see if it's null if it's not null then we have the url passed as input now currently we're not actually going to use this url yet we're just going to load the dummy image for now in the next video i'm going to show you how to asynchronously load these resources from the internet we're going to be using glide for that so right now i'm just going to use the dummy image so i'm going to use an image composable just get that from the composable dependency now do bitmap equals image resource r dot drawable dot empty plate so this will be that empty plate image that we just got at the beginning of this video then we want to add a modifier to this so modifier dot fill max width whoops go to the next line and then we want to do preferred height and set that to 225 dp not for any particular reason i just think 225 dp looks good now set some kind of a content scale so we can do content scale dot crop so an important thing to know about this image resource function if i control click on this and you go up to the top here there's a very important kind of heading it says synchronously load an image resource synchronously being the key word here and it also says note this api is transient and will likely be removed for encouraging async resource loading so this this function is not good that's essentially what it's saying here it's saying this function loads resources on the main thread it loads it synchronously on whatever thread you call it in so this is not good this is very likely going to slow down our ui significantly because for every list entry for every recipe it's going to be loading the resource synchronously on the main thread so that's a big no-no with android development you never want to do anything on the main thread so again like i said we're just going to be showing this default image for now in this video and then in the next video i'm going to show you how to load the actual url using glide and we're going to do that asynchronously so just kind of you know put a pin in this and we're going to come back to it in the next video so now the next kind of thing in our column is that row that will contain the title and the score so i'm gonna do recipe.title again let to check to see if that title is null now create a new row in here and open this up make sure to get that jetpack compose import now we're gonna add a modifier to this row so right modifier equals modifier dot fill whoops i want to go to the next line dot fill maximum width and then add some padding and we'll do you know 12 dp on the top we'll do on the bottom we'll do 12 dp also so top and bottom 12 dp and then the start so the far right we'll do 8 dp 8.dp and then lastly end equals we'll also do atp so atp on the end the start 12dp on the top and the bottom just kind of bring everything into the center a little bit now let's add the contents of this row so the first one is the title so let's do text equals title and do a comma i like to move this to the next line just to make it look a little better now let's add a modifier to this text so modifier dot fill max width now this is something you probably haven't seen before i don't think we've gone over this i'm going to do fill max width and then specify 0.85 as a float so what i'm saying here is occupy the entire width up to 85 so in other words occupy 85 percent of the width then i want to do rot wrap content with and do alignment dot start so if we take a look at the finished version of the app here in this row this is the row that we're working on right here we have the title and the score we want the title to be aligned to the start and the score to be aligned to the end so that's what i'm doing here i'm saying fill the maximum width up to 85 percent that makes sure that there's 15 percent left over for that score section and i'm saying wrap the content width and align it to the start now the last attribute that i'm going to add is a styling attribute and we're going to reference that material theme constants file like i did with the with the with the rounded corner up here for our card we're going to access some typography so some styling for text so typography and i'm going to use h5 now if any of you are familiar with web development i'm sure you know what like you know what h1 is h2 h3 h whatever all these different h tags are different kind of heading tags so for this one i'm going to use h5 which is the second smallest h6 is the smallest h5 is the second smallest and then for the score so for this little section over here i'm going to use one that is even smaller than that so we're going to use an h6 for that and again these can be customized and we're going to be doing that later in this course next we're going to work on the rating so let's build another text composable down below and move this to the next line so this will be recipe dot rating and i have to call two string on this because it's an integer if you hover over the type here it is a nullable integer so i'm calling two string on that to you know cast it to a string so we can actually put it in the text now modifier equals modifier and we'll do fill max width so occupy the remaining width but that's only going to be 85 percent of or sorry 15 percent of the width because remember this one occupies 85 and then go to the next line and do wrap content whoops wrap content width and say alignment alignment dot end and one last thing we need to call on this modifier that we didn't need to call on the text modifier up here is the align attribute so i'm calling dot align and then doing alignment whoops alignment dot center vertically and i'm going to talk about why in just a second i want to draw a diagram for you because it's not going to make sense i don't think unless you see a diagram it's kind of hard hard to picture so now the styling as i said for this one is going to be material theme dot typography dot so the text for this one is going to be smaller than the text for this one h5 is larger than h6 so now why did i need to center this one vertically but i didn't need to center this one vertically so as i said this one's a hard one to picture without using a diagram so i'm going to draw a diagram so i'm going to draw this card here so just imagine this this is the card here's the card for you know this entry over here we have the title section down here and i know this is this this kind of height is much larger than you know this this height here but i want to really emphasize something so here's the image here's you know here's where your hamburger would be that you're going to eat here's the food up in the picture now down below here's the title and the rating so i'll just write the title in here in really big text let's say that's the title and then down here the rating would be much smaller so what happens down here in our composables the title dictates the height because this remember this one is the h the h5 element so the text size is bigger whereas this one is the h6 element so the text size is smaller so what this looks like here for the the rating is actually there's an invisible kind of alignment line that gets drawn on the top of the title and then the score whatever that score is gets aligned to the top of that so the distance from the top of the score to and then the distance from the bottom of the score to the bottom these are not even by default so what we need to do is we need to align this thing in the center so let me erase this and that's why we need to center it vertically so by calling center vertical it places this thing in the center so that the space here to here and the space here to here is the same so this is kind of aligned right in the middle of one another that's why we need to center this one and we didn't need to center this one this one dictates the height whereas this one just gets aligned by default to the top of that one so hopefully that makes sense to you now you know why we needed to align this one center it vertically whereas we don't need to center this one vertically so there is our recipe card now how do we use this recipe card well we are going to go into our recipe list fragment so it's going into recipe list recipe list fragment and scroll down and we can delete everything in here that we have currently we don't need to print anything to the log we don't need to add a random button or anything like that now we want to just display this list so here we have an observable data structure that we can now you know put into a list and for that we're going to use a lazy column and also notice here that you have lazy column 4 and lazy column 4 index which are deprecated they were deprecated in the new alpha 09 release of jetpack compose so that's why we're using this this other or the the newest way i guess you could say lazy column so click and enter on that if you use a constructor it forces you to pass the content as a function here you can do that so you could like you know have your content here and you know pass your content in into inside of the function instead you could also you know not use a function and then just open this up and you can put your content in here it doesn't matter whichever way you choose also you know you could you could do um attributes in here too like this takes a modifier you could just hold down control and take a look at all the things that it accepts you have a modifier lazy list state padding blah blah blah blah blah a bunch of different stuff here the only thing that we care about in this video is the actual contents of the list so there's a couple ways you can do this you can see here that it takes a lazy list scope or this is the scope for the content if i click on this and i go down to this lazy list scope thing so control click on this there's a bunch of different uh interface functions so you can use this function here which is a list of items and there's the item content so that would be like oh i'm getting a bunch of updates here that would be like our our recipe card fragment you could pass that you could use the single item so this is for a single item you could use the items index which is the same as the items except for there's an index parameter that's passed to each item so that's kind of convenient so those are the three kind of functions that are available we're going to use the items indexed one because later when it comes to writing some some of our business logic in the view model that index is going to come in handy so so i'm not going to explain too much about why we need the index right now but just know that we will be using that later so now go into recipe list fragment and inside of our kind of our scope here our lazy list scope i can write items indexed that was one of the functions that was available in that interface it takes an argument called items and i can set that equal to the recipes and then i want to open this up and i can do i can tell it you know what what am i what am i inflating for each individual recipe and this this items index remember it takes two arguments or it passes two arguments into the lambda the index and then the list item itself for us that means a recipe so what it'll do it's gonna loop through each one of the recipes it's gonna spit out an index it's gonna spit out a recipe and then we can tell it what we want to show but we want to show a recipe card so getting that import i can say recipe equals that recipe and on click we'll just set that equal to an empty function for now but we will be handling the clicks later in the course because obviously if you click a recipe like if you go to the finished version of the app you click on a recipe that takes you to the next fragment all right so we're almost done just going to go into the view model now so go into recipe list view model and i couldn't remember what i did in the previous video or a couple of videos ago in the view model here so i'm just going to change this up a little bit i'm going to write an init function and just call new search i'm not sure if i actually built this function in the video where i built out the repository or built out the vm v model i think i actually just wrote um i think i just had like this inside of here so build out a function called new search and then just cut this out paste it in here and then just call new search and that's all i want to do so we're going to be searching chicken and we expect to see some some list results now just keep in mind though in our recipe card remember we are showing that we're just showing that default image we're not showing the actual image so the image will not be coming through we're going to work on that in the next video so let's run this and take a look at our list all right so there's our list and it looks like it's working we have our titles we have our scores and we have no images also if i scroll this is extremely laggy it is like crazy crazy laggy there's no way this is usable and that's because of that synchronously loading function for the image resource right here remember again i just want to mention that we're going to be fixing that in the next video and also showing the real images not just the default image so there you have it that is the equivalent of a recyclerview with jetpack compose and the equivalent of a card view with jetpack compose and i know there's lots of questions still up in the air like you know what is this material theme thing how do we you know asynchronously load the real images what are we using the index for lots of stuff i know but this video is already long enough and we're going to be going through the rest of this in the rest of the course now before i go of course do not forget to leave your engagement do not forget to leave a like you guys have been doing a great job and also for those of you who have not registered on my website yet make sure to register on my website i'm going to be publishing all of these lectures probably early next week on my website it'll be free there also but it'll track your progress so you get you know as you complete the lectures you get like a check mark says you've completed it it tracks the the progress of each individual lecture that you watch so like if you watch you know sixty percent of a lecture it'll say that you watched sixty 60 of that lecture if you come back next time you can carry on from that exact same point it's just a more convenient way to watch the course so again thanks for watching and i will see you in the next one you
Info
Channel: CodingWithMitch
Views: 11,839
Rating: 4.9757085 out of 5
Keywords: jetpack compose recyclerview, jetpack compose list, jetpack compose lazycolumn, jetpack compose lazy column, jetpack compose lazy column for, jetpack compose lazy column for indexed, jetpack compose card, jetpack compose cardview
Id: hnNIX6dUPC8
Channel Id: undefined
Length: 19min 53sec (1193 seconds)
Published: Sun Dec 20 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.