 Hey everybody, this is Brian and welcome to the 41st Flutter Tutorial. Today we're going to do something a little bit different. I've been getting a lot of feedback and some people will kind of want to see a quote-unquote real world application. So we're going to make a quote-unquote real world application. I don't edit my videos so you see all the successes, challenges, and complete and utter failures and spelling mistakes. So there may be parts of this you're going to want to fast forward through. I try to whip through it pretty quickly, but being what it is, it usually is filled with errors. So we're going to make a pizza ordering app. Now while this won't actually order a pizza, it will be the skeleton from which you could order a pizza if you had your own pizza company. So from here, we're going to create a directory. We'll call the screens. And we want to create another directory here called images. Now you notice how images is actually at the root. It's not down in the libs here. And we want to create another directory here called code. I'm just kind of showing how I break things up a little bit here. All right. So what we're going to do here is we are going to build an application that allows the user to order a pizza and select toppings and size and things like that. And I'm going to start the emulator and kick that off in the background while I'm sitting here talking. All right. Now, first thing we want to do is create a dart file here. We'll just call it pizza. And we're making this in the code folder. And this is going to be the actual state of what we're saving here. So class pizza. And in the past, what we've done is we've had the state per page. And what we're going to actually do in this is we're going to make this class on one page and then hand it off to another. And we're just going to make the list of pizza sizes that are available. And we're making this static because we want to be able to access this from outside of a instance of the class. You'll see what I mean here in a little bit. All right. Now we want to say string size, the initial size that we're going to let them choose equal sizes. element and we want zero. That has to be static or we won't be able to use that as an initializer. And then we want the map. We're going to call this toppings. Caps key didn't want to work there. I've been asked a lot of questions like how many of Flutter apps have I built? What have they been used for? Things like that. Really, they've been a lot of internal prototyping of future projects that I'm working on. I've actually been looking at getting a, I want to say, a prototype up and built for a big project. And I've been looking at different, make sure I spell pepperoni, right? Or that I'll never live that out. All right. There we go. Yeah. You guys will never let me live it down if I spell it. Although I always misspell everything. It's like a curse. But anyways, I, I want to find just like the perfect mobile framework to work with. And it's got to be cross platform. It's got to be a few things. And it's got to work with Firebase and Facebook integration. And it can't cost money. It has to be open source. There's a few requirements for this project. And that's what really led me to Flutter. So we're going to add just some toppings here, pineapple. Usually I'm like a pepperoni sausage extra cheese kind of guy. I don't really like pineapple and sardines. And I'm just adding a bunch of weird stuff. Onions, I guess those are all right. I usually just pick them off, throw them in the trash. Mushrooms. See peppers. I don't know. I got to think of some crazy stuff here like, I don't know, pickles. We'll call it the pregnant pizza. Maybe chocolate. Not sure. Geez, I misspelled chocolate. That's embarrassing. All right. What else could you throw on a pizza? I'm just trying to think of some really off the wall. Bananas. Why not a banana pizza? Banan. There we go. And one more. Why not? What could we throw on a pizza? Olives. There we go. All right. So really what this class is going to allow us to do is hold the state in memory as we pass it from one page to the next. And we've got the size. I should say the sizes that are allowed for the user to pick the default size, which is going to be the first one when this class is first created. And then we've got a map of toppings. And they are all false initially. All right. So that is in our code file here. Now we got to create some screens. Dark file. Here we go. Call this home. Home is kind of like always my de facto. What I'm doing next is going to just build out the rest of them. We want order. This will be where they actually order the pizza. And I've got to kind of slide my notes here a little bit. And then one more, which we will call review. This will be actually after they've, they've selected the pizza and their toppings and then they want to review their order before submitting it. That's kind of like the typical way of doing something. So we're just going to because these depend on each other, we're going to work backwards here. So what we're going to say is import and we're going to import the package flutter material. And then we're going to import the package pizza demo. And we want to be in code and we want to import the pizza dot dart file. That is our code file that has all the state goodness here. Then we'll say class review extends. We want the state list widget because we're not going to hold any state here. And we want the pizza called pizza order. And that's just going to be null initially. And then we want a list with string. This is what we're going to just kind of convert our pizza order to. And we could have wrapped this functionality directly into the pizza class. But I just kind of wanted to separate it so you could really see. All right, so we've got that and that. Now what we need to do is let's just get rid of this complaint here override widget build the context context. All right, that is going to include the body here. So we need to return a scaffold. And now it'll stop complaining for a minute. All right, so a couple of things need to happen on the review page. And this is the final page right before they submit their order is we need to actually take the existing order and render it out for them to view. And then, you know, basically have a button for them to do something with. So to render that out, we need to actually create a list. And then we're going to present a list view to the end user. So what we're going to say here is review. This is the constructor of the class in case you're still fairly new. So to use this class, you're going to have to hand us an existing order basically without that you just can't create it. I want to say pizza order equal order. And then from here, we're just going to say we're going to add the value of the size will say size equals. And then we want the then we're just going to say, let's add, and we're just going to add a blank line here. And then we're going to do, we're going to save a little bit of time here. And we're going to say pizza order dot map, actually toppings dot map, this is why I put it in a not map. This is why I put it in a map. So we could do the for each. And then we're just going to say bang, bang, and then do that, create our anonymous function here. So then we got the name and the value. And we're going to say if value then add the name there. So pretty easy to understand when we create an instance of this review dot dart, we are going to take the existing order out of the constructor, we're going to add it into our pizza order variable. And then we're going to generate a list, which we're going to present to the user in the form of a list view, which we've done before. So down here in the scaffold, we are going to say app bar new app bar, you messing up on me here. Well, title, okay, say review pizza order. And then in the body, we're going to say new container can do 32 padding. And let me get rid of this little bottom thing so we can see what we're doing here. Now, child, we want a new column. In the column, we have the children. And then we have our array of widgets. So we're going to say new text. And let's actually break this down a little bit here. And we want the font weight to be the font weight bold. So we're just going to boldface that review your order. And now that we got that, I think I'm just going to collapse that back down into one long one. Just to keep it nice and neat. Sometimes I get overly picky about this sort of stuff. All right, so we have our text. Now, this is something that if you're kind of zoning out on me, you're going to have to kind of pay attention to a little bit here. What we want to do is add a list view, like we've done in the past. The problem is, if your list view goes outside of the bounds or the visible area of the material that you're working with, it will display this ugly yellow and black bar. And you'll probably see that later on tutorial, but I'm going to add this just to get rid of it. It's a new expanded. And what expanded does is it well expands as far as you need it to go really without getting overly technical. And from this, we're going to say list view, that builder. And then of course, we do our item builder from that. So what we need to do now is let's break this down. We've got our item builder null. And let's do shrink wrap is true. That way we don't run in any bounding issues. Item count is equal to the list that count. Whoops. That's that length that count. And then for item builder, this is where we want to say the context context. What is this thing complaining about? No, can't be assigned to the parameter type. Well, we're not giving it no. Oh, I know what we missed. There we go. That should make it happy. So in here, what we need to do now is break this item builder out and actually have it build the items. We've done this before, but you know, just so we understand what's going on here. We're going to just simply return a new text. Pretty simple what we're building here. Let's get rid of that. And we're going to return the element at index. So really, we're just saying, hey, the list that length of the item count for the item builder, we're just going to go through each item and then print out each line of that list. Pretty simple, pretty easy to understand. There is our review page. And now working backwards, we're going to go to our order page. Actually, I think we're going to fast forward. We're going to go to the home page because I want to actually run this and display something here. So I'm going to say import. And we'll say package. And we'll do the flutter material package. Class home extends and we want the stateless widget because we're not holding a state at this point. And we want to override, maybe override the build function. I've had a couple people ask me, not just with these flutter tutorials, but other tutorials, how hard it is to actually make a tutorial. And it's pretty challenging trying to think, type, and talk all at the same time is not really my forte. As you can see, I'm making some very gnarly little mistakes here. So the home page is going to be very simple, but there's going to be a key element that I don't think we've gone over yet. We're going to just, you know, how to display an asset image. So what we're going to talk about is getting that in there. So we'll say app bar equal new app bar, title equal new text, pizza demo. Why not? And then from here, we're going to say body, just get our padding in there. And then we're going to say, Oh, do I want to center this? I want to just column it. I think I want to just, you know, I want to back this out a little bit. I do want to center that. There we go. Oopsie. There we go. There. So we're just going to center this container and then in the container, make a new column. And then in our children, we're just going to have simply two widgets in here. We're going to have the image asset and the raise button. Now, before we do the image asset, this is going to be key. We have to actually add the image in. So we're going to go to I have this little pizza image. If I can just blow this up, that's what it looks like. So I'm just going to copy this, literally copy it and then go over to my images folder and paste it in and make sure that it's in there. Now I do want to check one thing real quick. I think it's this pubspec.yaml file. And yeah, you see how it didn't add the asset in. So we're going to have to add that in. So let's, and it says literally to add assets to your application like this. So we're just going to go bang, bang. And we'll say images and we're going to say pizza.png. Pretty sure that's what it's named. And that's the full path to it from the base or from the root. So it's in slash images slash pizza.png. Just make sure that is in there. Pubspec's been edited. Pub failed. That's not good. What did we screw up here? Let's go back and look at that. Oh, that's why. Let's try pounding that out like that. That should work. Okay. So if you're wondering what the heck that was all about, it's got to be tab indented. There's just certain parser that runs in the background and it wasn't tabbed. So putting that tab in there, suddenly it magically knew what I was talking about. All right. So what from here, we're going to say new and we're going to say image.asset. I screwed that one up. Say new image.asset. There we go. And then it wants the fully qualified name here. So we're going to say image and then from there we are going to say new raise button and then expand this out. And we don't have the navigator in there yet. So let's work on our main real quick here. And we want to import the material app. We want screens and we want home.dart. Right now I'm on a mission just to get that homepage showing. So we're going to do a run app. My app doesn't exist yet. We're going to build that super quick. And then we'll say class my app. And we're going to extend a stateless widget out from here. We need to override. You guessed it. And then we're just going to simple do navigation like we've done before. We're going to say return new material app. And then from inside the material app we're going to do our navigation. What is this thing grabbing and complaining about? Does that build app? No, it doesn't. Some type blah blah blah. Why is that complaining? Widgets build context? Did I misspell something? See this is the part that drives me. That's about not editing my videos because you'll sit here for about 20 minutes watching me trying to figure this out. Invalid override. Build context isn't a subtype. Of course it is. Oh I see what it is. It's not widgets. It's widget. Derp. I feel stupid. All right. So there's our material app. And there we're going to say title. And we're going to say navigation. And then of course our routes. And we want the widget builder. Now that we've got our string widget builder we are going to simply say bang bang and then create our routes. And we're just going to copy and paste this bad boy because why not? Save some time. And from there we can just copy and paste this whole thing. And make our three routes. Home, order, and review. Boom. And we're just going to let's flesh out this order page real quick. We're just going to do the bare minimum on the order page. All right. Import package material. And then we're going to say extends the stateful widget. And we're going to override the state which doesn't exist yet because we're going to build it here in just a second. Always makes me nervous when I type things out before I've actually created them because then you know IntelliSense isn't helping me. And I have a nasty habit of typing faster or slower than I think sometimes or faster than I think. So we are just going to make the state of the order. And then we're going to, you guessed it, override the build. And from here we're just going to return a new scaffold. And I kind of want to mess with this one last just because this is going to be the kind of the meat of the application. And I really want to make sure we get this right here. So we're just going to say new center. And then in there we're going to say child equals new container. And then child equal new. What do I want to do here? New column. And we'll just leave that blank for now. I'm going to add the padding in there. That ginsets all 32.0 because that's kind of my favorite here. All right. So now it's time for us to actually try to give this thing a build and make sure it actually runs. We've got kind of the bare bones of our application. And so the main Dart file, we are going to actually we need to import some things. So this is going to complain. Review. All right. Now it should kind of somewhat run. So our main Dart file, we just have our material app and in there we have our routes. The goal of this is to bring up the home. And we're going to see if we can get that to work real quick here. We are actually missing a piece here. Home equal new home. Otherwise it won't do anything. There we go. So we're going to have our initial route in there. All right. Let's give it a whirl and see what breaks and what works. Pull up our Android emulator here. I've had a few questions about why I use the Android emulator instead of the iOS emulator. It's very simple. It's just because I'm programming on my Linux machine. If I was programming on my Mac, I would have a choice of both, which you could probably just do both at the same time. I haven't really gotten into that simply because I have my microphone plugged into my Android box. Android box has been kind of my main development box. All right. So there is our home page and the order button is grayed out because we haven't put that in there yet. We're going to do that navigator next. We can see there's our beautiful pizza icon and we're going to just start fleshing this thing out. So let's switch over to home and there's our on press as null. We're going to say on press bang bang. And then we're going to say, whoops, the navigator dot of context. And then we're going to just do a push name. And we're just going to push over to the orders page. Hot reload should grab that. Yeah. Now we can actually click our button and nothing happened. Oh, I think we're missing something here. Import package. Whoops. That's not what I wanted. Pizza demo screens order. I bet we just forgot the import here. Let's try that again. Hot reload and nothing happened. This should work. Let me rerun the whole thing. Maybe just didn't pick it up. If it doesn't run this time, I'll actually read the error message. Not a fan of modern day error messages. Come on. All right. What's going on here? Blah, blah, blah, blah, blah, blah, blah, blah, blah. Exception caught by gesture. The following assertion could not find generator of route orders. What? We have it right here. Oh, that's why order hence spelling error. All right. Let's try that again. Now suddenly it goes to our order page. All right. So we have basic navigation. We have an image and we're going to start actually just doing the order. The review page should be done. So we just got to really focus on this order page. Once we hammer this out, we should be pretty well done here. So let's flip into order and we got some work to do here. So we want to import our package. Screens review. We want to import the package from the pizza demo code pizza because we're going to work with that class. We're going to make a simple order here. And from here we need to actually go into this and actually build our state out. Say pizza, pizza order. Able new pizza. No, in the sense. Why have you betrayed me? All right. There we go. So we're going to have a couple things in here. We're going to have a, let me pull this up so you can actually see what the heck I'm talking about here. The way I want it is we're going to have a drop down box here so we can select the size. And then we're going to have a list of toppings in a list view and then a button at the bottom so that we can actually review the order. It's pretty simple, but it's a little bit of a learning curve to get this to work just right. So let's actually just start working on it. And we are going to say new drop down button, drop down button. Where are you at? There you are. Then we have items and null. So what we want to do here is we want to actually give it our template, which is going to be a string, which I'm not sure if that's really needed or not, but we're going to add it in anyways. So our items are going to actually be the pizza class that sizes. And then we want to map that. I don't think we really want the on change, do we? Yeah, we do. Hold on a second. Let's do this. Let's go. We want our value, what the initial value to be the order that size. There we go. That's what I was getting hung up on. What is this thing griping about? Too many positional arguments. What do you mean there's too many positional arguments? Why are there too many, zero expected but one found? What are you griping about here? Not liking this. Something's going on. Let's just start over on that. New drop down button. Bang. Item null. Oh, duh. I feel really stupid here. Children. Bang. Okay. That makes more sense why it was griping. I was hung up on that button. Anyways, new drop down button. That looks a little cleaner. Okay. Like I said, sometimes typing, thinking and talking all at the same time really don't mix well. So pizzaordered.size. So we want the initial size and then the on change, we're going to actually make a function here. So let's just mess with that first. We want to do the set size. Let me look at my notes, make sure I'm actually doing this right. Yep. All right, from the set size, we are going to just simply do a set state. In the set state, you might have already guessed what we're going to do here. We're going to say pizzaordered.size equals the size. And we should actually say value that we were not really confusing. Anybody here? All right, now in here, we can actually say our have to scroll down, make sure I'm in the right spot with my notes here. It gets really confusing if I get kind of off here string value. There we go. Now comes the really confusing part. I really don't like the way that the drop down button is handled, but it's just as what it is. So for the items, we have to do the pizza order. Actually, no, we don't. Sorry. Sorry. Sorry. We need to do the pizza that sizes that. And then from here, we do the map. And this is where it gets kind of really confusing for people. So we're going to say string value. And then we're going to map this accordingly. And then in the map, we're going to return a new thing. It's a drop down menu item. And then there's our child null. So let's break this out a little bit so we can see what we're doing here. All right. So the initial value of this, or I shouldn't say the initial the value of this is value. And then the child itself, we're just going to make a new row. And then we're going to have children in here. And in the children, we're going to say new icon icons. What was it? Local pizza or something like that. I found this really cool icon. There we go. Local pizzas and icon. I was really surprised when I found a pizza icon. I was like, yay. It's little things in life that really make us happy, you know. And then here we're going to say simply size equals and then the value. Then in case we decide to mess with any more properties, hot reload, we're going to actually just start this whole thing over again. I did a lot of typing. I wasn't really trusting hot reload. And boom, we are presented with a big, big fat error. And we're going to have to figure out, whoops, nailed my microphone. All right. Let's see here type. Map list, iterable string, blah, blah, blah is not a subtype of list drop down menu. Say what? Map list, iterable. All right. So basically what it's arguing about is in here. I bet I know what the problem is. We didn't give it a type. Let's just stop this thing again. See what it's griping about here. Map list, iterable string dynamic is not a type of list drop to menu item string. Okay. Well, what is the problem with this? So we got drop down button string, pizza order sized. Oh, I see what's going on here. Okay. I think I see what's going on here. We're missing a list here. Yeah, two list. That's what's going on. If this is right, I'll explain the voodoo magic that just occurred. Tick tock, tick tock. Let's check our order and okay. Yes, what I thought it was. So now we've got a drop down list and we've got the on select. So we're on the on change that's tracking in the state. So the thing that I was missing here was this dot to list of this whole thing. And if you take that right there should highlight it. Yeah, it's on the pizza map. It's in the items because the items is expecting a list and I was just giving it a map. So I was just giving it a whole wad of data rather than an actual list. And that's why I was complaining. Oh, some of these error messages. All right. Anyway, so we've got this. This is a major hurdle right there. The rest of this should be quotey fingers should be fairly straightforward. All right. So now that we've got that we're going to new expanded. And I had to actually go into the the flutter live chat they have on their site because I didn't know what the heck was going on with this. I tried just adding a list directly and it went out of bounds and I'll actually demonstrate that in here in a little bit. And it showed that ugly bar that you guys may have actually encountered by now. Let's call it continue. All right. So in our expanded, we want to put a new list view in here. We'll do list view builder. And as you can see, our item builder is going to be null initially. Let's just get rid of that blank line. That way it doesn't get all confusing. All right. And we can just say should grab true. Probably don't really even need that. But I like putting it in there. And then item count. And the item count here is going to be the length of the toppings. Because remember that's a map under the hood. And then the item builder, we want to actually do a non-function here. And in this, I keep forgetting that index. I always forget that. That's my only really gripe about this. Otherwise, it's very beautiful the way that works. Now we're going to return a new checklist title, which we covered in previous tutorials. Let's put the semicolon up here. And we want to add a few things to this. First thing we want to do is the control, oops, control affinity. The control affinity, we want the list title control affinity to be leading. That puts the checkbox in the left instead of on the right. And then we want the title. And we want this to be the, oh gosh, what was it? The pizza order toppings. Keys.ElementAt. And then the index. Remember the key is the string. So we want the string portion, not the boolean portion. And then from there, we want our value. And this is going to be, we can just actually grab this whole thing. Don't be difficult. All right. So let's hot reload this to see if it works. Yep. As you can see, there is now our toppings. And there's our button. They're grayed out because we don't have the on change handler. So let's go ahead and wrap that in now. And let's do this. Set topping. And in the set topping, we of course need a int index and a boole value because we want to know the index and the value of that. And we are going to, of course, set state. And in our set state, we are just going to very simply say string key equal the actual key here. And then we're just going to say, whoops, set the value of that key. Now we need to wrap this guy into this. So where is it right here? Unchanged. Unchanged is going to simply be the, now it has the index and the value. Let's flip back over. Suddenly they're enabled. And we can actually click and unclick things. And it's tracking that in state as we do that. So every time we select or unselect, it's calling this set topping. And it's going through this little function right here. And we can actually scroll through the list and we can set the size. Last but not least, let's actually set the on press to this raise button. And we're just going to say, bang, bang. And this is going to be a little bit different. What we want to do is we want to do a push and notice how it has a context and now it wants a route. So we actually have to build the route manually here. So on our route, we're going to say new material page route. And we need a builder here. And I'm going to kind of break this down a little bit. That way we can see what's going on here. The builder, of course, is going to be the build context. And we want a new review because this is where we're sending it to. Now review, of course, you can see how it just popped up and rinded me. Order is null. Well, we don't want a null order. We want our pizza order in there. Why is it not doing that? Come on now. I know what's doing. All right. So we are sending our pizza order to it. Let's get rid of that semicolon or it's going to describe complain. So really, if you're following along, what we're doing here is we are taking that. Let me rerun the whole app here. We're taking the class. We're creating it, the class being this pizza.dart file, and then we're manipulating it. So no longer do we have variables locally that we're doing? Well, we kind of do. But now we're going to push this off to the review page. And you can see here's a review your order and it just has your toppings in there. And we can go back and the state is still perfectly there. So let's say we only want pepperoni and sausage because that's my favorite. And I'm too skinny to eat a large by myself. So I want a medium. So we have a medium with pepperoni and sausage. So that in a nutshell is kind of how that works. Now, some caveats to this is, A, it's not backed up in the cloud. That's the problem. So we will be doing, hopefully, in the near future, Firebase tutorials. Also, there should be a button down here that you would do a HTTP push to Pizza Hut or Little Caesars or Dominoes or whatever. You order your pizza from Bob's pizzas or whatever. Some other things is the problem with programming, you ever hear the expression, there's more than one way to skin a cat, kind of a gruesome expression, but there's more than one way to solve a problem. So this may not be necessarily the solution you're looking for. This is just something that I do for simple apps where I just make a class that holds all the settings I need. And I manipulate that as the state and then push that class over in the, where is it? The material page route. I just take that variable, that instance and just shove it straight over into the other file as part of the constructor here. That way, I just get the state and I don't have to worry about rebuilding it, loading it from a database or anything. It's all in memory, it's all good to go. Pretty simple, pretty easy to use. Now, one thing I did want to go over here, where is it? Order. Expanded. Yeah, this is what I was looking for here. I'm going to comma that. That didn't work out the way I planned it. Please hold. All right, so we are just going to take this whole chunk here and we're going to comment that out. But we are going to grab this list view and put this in here. Just so you can see what happens. You see already this thing right here. That was the first indicator that something went boom. And when you look at it now, this is why you need that expanded because the list view goes down lower and it puts this ugly thing here. And I, for the life of me, could not figure out how to get rid of that. That's simply why you put it in an expanded. So we're going to just get rid of that and come at this and come at that. Put everything right back the way it was and suddenly magically it works again and we can scroll down and life is good. So some key concepts that we've covered in this that I don't think we've covered in other tutorials is how to put an image up here. How to make an expanded, meaning if you try to take that list view and just put it into like a column or something you need to have an expanded in there. Otherwise, it shows that ugly bar and how to manipulate the state in another class, basically, or use another class as your state, I should say. And then, you know, just passing that class between them using the material page route. So this is kind of, I would say, not a super elite difficult tutorial, but this is definitely not on the beginner side. So you guys have been wanting kind of a real world example and I'm hoping this fits the bill. I'm hoping this answers a lot of like organizational questions and how you structure things and how you get images in and how you pass variables back and forth. That was a lot of talking and I'm pretty well spent. So for the source code for this and all of the tutorials, visit my website void realms.com. It's out in GitHub's and join the void realms Facebook group. There is 1800. We just breached the 1800 mark 1800 other programmers out there, all other languages and frameworks definitely help you with your problems. And if you're feeling so inclined, like if you're running a business, the site is 100% funded off donations. That's why I do not include advertisements on YouTube. So I'll feel free to donate. That's it. Thank you for watching.