1 00:00:02,300 --> 00:00:07,270 To style the separate items, I'll again create a separate component and I'll name it 2 00:00:07,350 --> 00:00:11,620 mealitem.js, the name as always 3 00:00:11,640 --> 00:00:15,320 is totally up to you and in there, you know the game, 4 00:00:15,320 --> 00:00:18,200 we create a React component by importing React, 5 00:00:18,440 --> 00:00:25,360 we'll also probably need view, text and stylesheet and maybe also some other things from React 6 00:00:25,460 --> 00:00:32,610 Native. Then we set up the component, meal item, where we receive props and where we then return some jsx 7 00:00:32,610 --> 00:00:38,010 in the end. Set up a stylesheet here, store it in a styles constant with stylesheet create to 8 00:00:38,010 --> 00:00:46,090 which we pass an object and in the end, we export our meal item here as the file default. Now with that 9 00:00:46,090 --> 00:00:48,100 here, in meal item, in this component, 10 00:00:48,100 --> 00:00:54,040 we of course need to return some jsx code for that meal item and that's something I get from 11 00:00:54,040 --> 00:00:55,750 the category meal screen. There 12 00:00:55,810 --> 00:01:02,260 I have this view with my text in here, that's in the end what I want output, a bit more complex than that 13 00:01:02,710 --> 00:01:07,150 but I'll cut it from there and move it over to meal item and there, return 14 00:01:07,150 --> 00:01:12,380 this view here but of course we're not done with that. For one, 15 00:01:12,380 --> 00:01:17,390 this also should be touchable because we can select a meal, we can select such a recipe to be taken to 16 00:01:17,390 --> 00:01:21,010 the detail screen, so I'll import touchable opacity. 17 00:01:21,020 --> 00:01:25,910 Now of course, you could again make that differentiation and use the ripple effect with touchable native 18 00:01:25,970 --> 00:01:27,880 feedback on Android if you wanted to, 19 00:01:27,920 --> 00:01:35,270 I'll go with touchable opacity for now and wrap my view here with touchable opacity, 20 00:01:35,420 --> 00:01:44,350 like this so that we can actually tap our item here and onPress, I actually want to trigger a function 21 00:01:44,350 --> 00:01:49,000 that I expect to get on a property which we're not passing into the meal item yet but because we're 22 00:01:49,000 --> 00:01:54,460 not using the meal item yet anywhere but which I will pass in in the future, maybe we name this on 23 00:01:54,460 --> 00:02:00,820 select meal or just onSelect, whatever you want, I'll name it onSelectMeal and I expect to get that 24 00:02:00,820 --> 00:02:06,950 prop on the meal item when we then use it in jsx. So that's the touchable opacity, 25 00:02:08,790 --> 00:02:16,050 in there I have my view with the title and actually that view should be a bit more complex than that. 26 00:02:16,740 --> 00:02:24,150 I want to have a view, a nested view in there like this and another view below that, 27 00:02:24,180 --> 00:02:25,530 so I want to have two rows. 28 00:02:25,530 --> 00:02:31,060 This will be set up as a column but these two views here will be set up as rows here. 29 00:02:31,230 --> 00:02:38,280 The first view should also render a background image, so that the title sits in front of this background 30 00:02:38,310 --> 00:02:39,130 image, 31 00:02:39,180 --> 00:02:44,730 the second view, the second row here should render some details about the selected recipe, 32 00:02:44,730 --> 00:02:47,270 like its complexity and duration. 33 00:02:50,190 --> 00:02:55,530 So let's start with that before we later add the image, on both these views, 34 00:02:55,560 --> 00:03:00,660 I will therefore add the style property and point at styles 35 00:03:03,050 --> 00:03:08,860 meal row or whatever you want to name this because it will be a row in my meal presentation here 36 00:03:10,030 --> 00:03:18,140 and I'll add meal row down there therefore and set the flex direction here to row of course because 37 00:03:18,140 --> 00:03:23,150 that should be rows of data. Now around the overall item here, 38 00:03:23,170 --> 00:03:27,290 I'll wrap another view where I want to set up a general style 39 00:03:30,050 --> 00:03:34,850 of styles meal item and meal item, 40 00:03:34,850 --> 00:03:40,670 that also is configured here in the stylesheet of course and there I want to give each meal a height 41 00:03:40,700 --> 00:03:46,940 of 200 let's say, each item in the list here and a width of 100% to take the full 42 00:03:46,940 --> 00:03:55,390 available width and also maybe a background color of this grayish 43 00:03:55,430 --> 00:04:00,570 look here, we can see whether we want to keep that, for now I'll use that. 44 00:04:00,810 --> 00:04:04,770 Now we can use the meal item here and we're not done with it yet but we can start using it here in the 45 00:04:04,770 --> 00:04:14,560 category meals screen by of course importing it, import meal item from the components folder and there, 46 00:04:14,560 --> 00:04:25,230 from the meal item file and then render this here, so return meal item here like this 47 00:04:25,230 --> 00:04:32,010 and of course we now need to pass in some data, data like the title which we get from itemData.item.title 48 00:04:32,010 --> 00:04:38,850 and the onSelect prop which I expect to get in the meal item which we in the end hook up to 49 00:04:38,850 --> 00:04:42,840 touchable opacity's onPress prop, onSelectMeal, 50 00:04:42,840 --> 00:04:44,030 that was the name I chose, 51 00:04:44,070 --> 00:04:46,820 that's also something we need to set up here 52 00:04:46,830 --> 00:04:51,330 when we use the meal item and this should point at a function which for now doesn't do anything but which 53 00:04:51,330 --> 00:04:55,090 will later load the detail page for that meal. 54 00:04:55,110 --> 00:05:00,300 So now we get the title on the title prop, hence the meal item, here when we output the title we do this 55 00:05:00,300 --> 00:05:01,590 with the help of props.title. 56 00:05:01,740 --> 00:05:09,260 If we now save this, we should actually be able to see something here, so let's wait for this to 57 00:05:09,260 --> 00:05:10,580 reload 58 00:05:10,580 --> 00:05:16,730 and yes, we see our meal here and certainly not too beautiful but at least, we see a bit more than before. 59 00:05:16,730 --> 00:05:21,620 Now what I'd like to have here is a little bit of spacing around the list but inside of the spacing, 60 00:05:21,710 --> 00:05:26,930 the list item should take the full available width and not just the width of the widest item which is 61 00:05:26,930 --> 00:05:28,850 currently what's happening. 62 00:05:29,090 --> 00:05:35,800 And for that, we can go to the FlatList and there, add the style property and set this width to 100% 63 00:05:35,810 --> 00:05:39,470 to make sure that the FlatList itself takes all the width it can get. 64 00:05:39,470 --> 00:05:42,020 With that, we should have to look we want here. 65 00:05:42,290 --> 00:05:44,710 Now of course, the meal items are not done though, 66 00:05:44,720 --> 00:05:51,380 they don't look the way I want them to look though we also slowly get there. Now in the MealItem.js 67 00:05:51,380 --> 00:05:53,680 file, we still have some work left to do though, 68 00:05:53,690 --> 00:05:59,840 for example this view here with the title will later also hold the image and therefore this should be way 69 00:05:59,840 --> 00:06:03,960 bigger than the row below it which will later just output some details. 70 00:06:05,500 --> 00:06:18,310 Hence here, I will merge my meal row styles with another style object, so with the style set up in another 71 00:06:18,350 --> 00:06:26,530 stylesheet object which I'll name meal header or whatever you want to name it and the same down there 72 00:06:26,530 --> 00:06:29,090 by the way for the details in the end, there 73 00:06:29,110 --> 00:06:36,920 I will merge this with styles meal detail, so that we have combined styles and let's start with the meal 74 00:06:36,920 --> 00:06:39,470 header which we can set up here. 75 00:06:39,470 --> 00:06:47,090 The meal header in the end will hold the image and also the title and I want the height of this to be 76 00:06:47,410 --> 00:06:49,580 let's say 80% of the available height, 77 00:06:49,580 --> 00:06:59,550 so this should be very very large. The meal details automatically will therefore get the remaining 20% 78 00:06:59,550 --> 00:07:07,470 obviously and to see whether that works, let's output some details here, so in that view here, 79 00:07:07,470 --> 00:07:10,020 in that row below our title row, 80 00:07:10,020 --> 00:07:13,420 I also want to have some text here and there I'll output 81 00:07:13,440 --> 00:07:21,920 let's say props duration and then m thereafter, for minutes because m duration will be a number which 82 00:07:21,920 --> 00:07:23,330 we treat as minutes. 83 00:07:23,330 --> 00:07:27,740 We just need to pass in the duration from the category meals screen of course, 84 00:07:27,740 --> 00:07:33,140 so when we use the meal item, besides passing in a title, I'll set the duration prop because we're now 85 00:07:33,140 --> 00:07:34,940 expecting this on the meal item. 86 00:07:34,940 --> 00:07:40,700 We get this from itemData.item which is our meal and there, we'll have a duration property because 87 00:07:40,760 --> 00:07:45,630 our meals as defined in the model here do have a duration property 88 00:07:45,800 --> 00:07:50,690 and indeed if you have a look at the dummy data, this here is your duration which is fed in. 89 00:07:54,760 --> 00:07:56,560 If we save this, 90 00:07:56,560 --> 00:08:06,850 now we see our duration down there and actually, we can still change that height here to even 90%, 91 00:08:06,910 --> 00:08:09,420 should be higher than it was here, 92 00:08:09,430 --> 00:08:10,630 that looks better 93 00:08:10,750 --> 00:08:14,830 and of course you can experiment with this as well. In the meal detail row, 94 00:08:14,830 --> 00:08:22,680 I also want to have some horizontal padding, so left and right of let's say 10 and justify my content 95 00:08:22,690 --> 00:08:32,650 here with space between, keep in mind it's a row so this will justify it horizontally, so that when we 96 00:08:32,650 --> 00:08:35,690 have multiple items, they will be nicely distributed there. 97 00:08:35,740 --> 00:08:45,740 So we have 20 minutes, let's output more information there by adding another text and there, output 98 00:08:45,900 --> 00:08:47,030 the complexity, 99 00:08:47,030 --> 00:08:53,140 so here I'll output complexity and thereafter, I'll output 100 00:08:53,140 --> 00:09:01,950 the affordability. Now we just need to pass in that data as well when creating our meal item. 101 00:09:01,990 --> 00:09:06,460 So here besides duration, we pass in complexity which we get here, 102 00:09:06,460 --> 00:09:16,420 itemData.item.complexity and affordability, that's of course 103 00:09:16,430 --> 00:09:18,530 itemData.item.affordability, 104 00:09:18,740 --> 00:09:28,910 like that and if we save this and let this re-render, now we see this output here. Still not super beautiful 105 00:09:29,000 --> 00:09:37,390 and we can definitely enhance this but a nice start. Now simple and affordable or our complexity 106 00:09:37,390 --> 00:09:45,000 and affordability therefore, that should be styled a bit differently. We know it will be text and therefore 107 00:09:45,000 --> 00:09:51,680 I can use some Javascript functions or methods we have available on strings, I will simply use toUppercase 108 00:09:51,770 --> 00:09:59,930 to convert it to uppercase entirely like this and now this should already look a bit nicer than 109 00:09:59,930 --> 00:10:06,590 before. Now you can still tweak the styling here, I'll go with with this styling here for now and let's now 110 00:10:06,620 --> 00:10:09,440 add a background image above. 111 00:10:09,440 --> 00:10:16,370 So for this, we wanted a background image behind this title text and thankfully, React Native makes adding 112 00:10:16,370 --> 00:10:23,930 such a background image really really simple. React Native ships with a built-in component, the image 113 00:10:23,990 --> 00:10:29,690 background component which we can use to render an image in the background as you would imagine by 114 00:10:29,690 --> 00:10:36,020 the name. You add it next to the component behind which you want to add it and you add it before that component, 115 00:10:36,020 --> 00:10:43,520 so here I add image background and on image background like on the normal image, you set a source. Here my 116 00:10:43,520 --> 00:10:49,220 source is a web image, so we pass in an object, if it would be a local image, you would use require and what 117 00:10:49,220 --> 00:10:54,380 you learned about local images earlier in the course but here, it's a web image, so we pass an object with 118 00:10:54,380 --> 00:11:00,560 a URI prop and there we use props image which is where I expect to get that URL in this 119 00:11:00,560 --> 00:11:07,370 component so of course we'll have to make sure we pass in the URL on that prop. I'll also add some 120 00:11:07,370 --> 00:11:15,000 styling here and that will be styles.bgImage which we're now going add to the stylesheet down there, 121 00:11:15,720 --> 00:11:22,110 wherever you want, maybe here, doesn't really matter. An important thing here, you have to set width and 122 00:11:22,110 --> 00:11:27,060 height because it's an image from the web and I will use them 100% for both because it should fill 123 00:11:27,060 --> 00:11:36,350 the entire space it gets. Now we just have to make sure we pass in that image prop here in category meals 124 00:11:36,440 --> 00:11:45,560 screen, so besides the title, here I also want to pass in itemData.item.imageUrl is the 125 00:11:45,560 --> 00:11:51,020 name of it, you can see that in the model, imageUrl, so that's what we're passing in and we pass this 126 00:11:51,020 --> 00:11:56,960 to the image prop because that's what we're expecting and what we're setting here in the meal item. And 127 00:11:56,970 --> 00:12:02,910 if you now save that and let's mix things up and test this on Android, just takes a bit longer to load 128 00:12:03,000 --> 00:12:10,410 which is why I typically use iOS here but now if we test this, we see our burger here. What we don't 129 00:12:10,410 --> 00:12:19,010 see anymore is our title though. To show the title again, make sure that you actually wrap image background 130 00:12:19,010 --> 00:12:27,480 around it, this is how you tell React Native which content should be inside above that background 131 00:12:27,480 --> 00:12:34,320 image. So now with that, here's our title, not that easy to read and we'll fix that but it's there again. 132 00:12:35,480 --> 00:12:41,050 So we're getting started with that recipe here, now let's make sure the title is a bit easier to see 133 00:12:41,050 --> 00:12:50,760 by giving it a style here, styles title which we can now set up down there and I want to set a font family 134 00:12:50,850 --> 00:12:52,210 of open sans 135 00:12:52,220 --> 00:12:55,490 bold, makes sense since we register this font. 136 00:12:55,590 --> 00:12:59,380 Give it a font size which we increase a little bit, maybe 22, 137 00:12:59,400 --> 00:13:01,310 you can play around with that of course. 138 00:13:01,440 --> 00:13:07,380 Give it a color of white to make it a bit easier to read and also assign a background color so that we 139 00:13:07,380 --> 00:13:10,600 can always see it, even if the background image would be white, 140 00:13:10,620 --> 00:13:16,800 in which case white text would be hard to read, by giving this an RGBA color which is a color that 141 00:13:16,800 --> 00:13:22,380 has built-in transparency so to say and this is simply a black color which is a bit transparent 142 00:13:25,490 --> 00:13:28,400 and now also add a little bit of padding here, padding vertical 143 00:13:28,390 --> 00:13:35,000 of five should look good so that the background colored box here doesn't sit right on the edges of 144 00:13:35,000 --> 00:13:42,950 the text that's inside of the box and padding horizontal of 12 maybe. With that we should always see our 145 00:13:42,950 --> 00:13:48,540 title and actually, we can probably increase that transparency here, 146 00:13:48,560 --> 00:13:51,790 decrease the opacity, 147 00:13:51,890 --> 00:13:53,210 yes that looks a bit nicer 148 00:13:53,210 --> 00:13:53,630 I think, 149 00:13:59,550 --> 00:14:06,420 like this. And the only thing I want to do now is I want to move that title down at the bottom of this 150 00:14:06,420 --> 00:14:10,250 image and therefore on the bgImage style which I have here, 151 00:14:12,450 --> 00:14:23,230 I'll set justify content to flex end because the background image automatically acts as a flexbox 152 00:14:23,230 --> 00:14:27,970 so to say, like a view, so we can justify our content in there 153 00:14:27,970 --> 00:14:30,400 and now we have that title at the bottom. 154 00:14:30,430 --> 00:14:39,460 We could now also center the text by going to the title here and adding text align center 155 00:14:39,580 --> 00:14:42,210 and in case it's too long, too big, 156 00:14:42,310 --> 00:14:46,400 besides of course shrinking the font size which I'll do a little bit to 20, 157 00:14:46,420 --> 00:14:53,080 of course you can go to that text here where you output a title and set the number of lines to 1 and this 158 00:14:53,080 --> 00:14:55,870 will ensure that the text is automatically shortened 159 00:14:55,870 --> 00:15:06,780 if it's too large, like here for the salad with cherry tomatoes. We also see a strange effect here on 160 00:15:06,880 --> 00:15:15,150 iOS where we have some extra background behind our text and not just the background colored box here. 161 00:15:15,160 --> 00:15:22,880 That's because I applied my background color and so on effect directly on the text, to fix this we can 162 00:15:22,880 --> 00:15:29,510 cut it from the title here and only set up the color and so on there and instead add a title container 163 00:15:29,540 --> 00:15:37,100 here where we add this background color and so on and wrap this container around our title, so an extra 164 00:15:37,120 --> 00:15:42,580 view we add here and it's quite normal in React Native to nest multiple such views and on that view, 165 00:15:42,580 --> 00:15:51,580 we can now add style, styles title container and if we save that, we should get rid of that strange behavior 166 00:15:51,580 --> 00:15:52,640 on iOS, 167 00:15:52,650 --> 00:15:52,860 yes 168 00:15:52,900 --> 00:15:55,590 now we don't have that extra box there, instead 169 00:15:55,600 --> 00:16:00,380 we just have one background color and the same on Android. 170 00:16:00,520 --> 00:16:04,270 So now this doesn't look too bad but I'm not entirely happy, 171 00:16:04,270 --> 00:16:10,480 I'd like to center my details here vertically as well and give it a little bit more space I guess and 172 00:16:10,480 --> 00:16:17,560 for that we can give the header maybe 85% of the height and on the meal detail here, 173 00:16:17,560 --> 00:16:23,650 keep in mind that our flex direction is row because we're merging meal row and meal detail here and 174 00:16:23,670 --> 00:16:26,080 therefore our cross axis is top to bottom, 175 00:16:26,080 --> 00:16:30,540 so if we want to center vertically, that is the cross axis on which we need to center. 176 00:16:30,550 --> 00:16:37,540 So here we can set align items which does the cross axis positioning to center and also change our 177 00:16:37,540 --> 00:16:43,280 color here a little bit to a little bit of a nicer color, 178 00:16:43,510 --> 00:16:49,170 this very light gray, #f5f5f5 might look a bit better, 179 00:16:49,300 --> 00:16:49,530 yes it 180 00:16:49,560 --> 00:16:50,800 definitely does. 181 00:16:50,800 --> 00:16:56,610 Now to make sure that we do really center vertically, we just need to be more explicit about the height 182 00:16:56,650 --> 00:16:58,660 our meal details should take, 183 00:17:03,480 --> 00:17:09,590 we take 85% on the header, so on the detail here, we can set a height of 15% 184 00:17:09,600 --> 00:17:17,230 obviously to take the rest, yes and I'd say this looks quite decent here, 185 00:17:17,420 --> 00:17:20,620 certainly list items with which we can work here. 186 00:17:20,630 --> 00:17:25,670 I'll now just add a little bit of a border radius because you know I like border radiuses, so I'll add 187 00:17:25,670 --> 00:17:33,500 a border radius of 10 here so that we have some rounded corners and with that, if you go back, we're almost 188 00:17:33,500 --> 00:17:38,820 there but you'll notice that the image actually doesn't respect the border radius. 189 00:17:38,870 --> 00:17:46,780 Now to fix that, on the meal item, we just have to say overflow hidden so that no child item can go outside 190 00:17:46,780 --> 00:17:49,130 of this space or this shape 191 00:17:49,130 --> 00:17:49,910 we're building here. 192 00:17:53,550 --> 00:17:56,880 And with that, that's a start, something we can work with, 193 00:17:56,880 --> 00:18:02,070 now of course we want to make sure that when we tap such an item, we actually go to the detail page.