To style the separate items, I'll again create a separate component and I'll name it
mealitem.js, the name as always
is totally up to you and in there, you know the game,
we create a React component by importing React,
we'll also probably need view, text and stylesheet and maybe also some other things from React
Native. Then we set up the component, meal item, where we receive props and where we then return some jsx
in the end. Set up a stylesheet here, store it in a styles constant with stylesheet create to
which we pass an object and in the end, we export our meal item here as the file default. Now with that
here, in meal item, in this component,
we of course need to return some jsx code for that meal item and that's something I get from
the category meal screen. There
I have this view with my text in here, that's in the end what I want output, a bit more complex than that
but I'll cut it from there and move it over to meal item and there, return
this view here but of course we're not done with that. For one,
this also should be touchable because we can select a meal, we can select such a recipe to be taken to
the detail screen, so I'll import touchable opacity.
Now of course, you could again make that differentiation and use the ripple effect with touchable native
feedback on Android if you wanted to,
I'll go with touchable opacity for now and wrap my view here with touchable opacity,
like this so that we can actually tap our item here and onPress, I actually want to trigger a function
that I expect to get on a property which we're not passing into the meal item yet but because we're
not using the meal item yet anywhere but which I will pass in in the future, maybe we name this on
select meal or just onSelect, whatever you want, I'll name it onSelectMeal and I expect to get that
prop on the meal item when we then use it in jsx. So that's the touchable opacity,
in there I have my view with the title and actually that view should be a bit more complex than that.
I want to have a view, a nested view in there like this and another view below that,
so I want to have two rows.
This will be set up as a column but these two views here will be set up as rows here.
The first view should also render a background image, so that the title sits in front of this background
image,
the second view, the second row here should render some details about the selected recipe,
like its complexity and duration.
So let's start with that before we later add the image, on both these views,
I will therefore add the style property and point at styles
meal row or whatever you want to name this because it will be a row in my meal presentation here
and I'll add meal row down there therefore and set the flex direction here to row of course because
that should be rows of data. Now around the overall item here,
I'll wrap another view where I want to set up a general style
of styles meal item and meal item,
that also is configured here in the stylesheet of course and there I want to give each meal a height
of 200 let's say, each item in the list here and a width of 100% to take the full
available width and also maybe a background color of this grayish
look here, we can see whether we want to keep that, for now I'll use that.
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
category meals screen by of course importing it, import meal item from the components folder and there,
from the meal item file and then render this here, so return meal item here like this
and of course we now need to pass in some data, data like the title which we get from itemData.item.title
and the onSelect prop which I expect to get in the meal item which we in the end hook up to
touchable opacity's onPress prop, onSelectMeal,
that was the name I chose,
that's also something we need to set up here
when we use the meal item and this should point at a function which for now doesn't do anything but which
will later load the detail page for that meal.
So now we get the title on the title prop, hence the meal item, here when we output the title we do this
with the help of props.title.
If we now save this, we should actually be able to see something here, so let's wait for this to
reload
and yes, we see our meal here and certainly not too beautiful but at least, we see a bit more than before.
Now what I'd like to have here is a little bit of spacing around the list but inside of the spacing,
the list item should take the full available width and not just the width of the widest item which is
currently what's happening.
And for that, we can go to the FlatList and there, add the style property and set this width to 100%
to make sure that the FlatList itself takes all the width it can get.
With that, we should have to look we want here.
Now of course, the meal items are not done though,
they don't look the way I want them to look though we also slowly get there. Now in the MealItem.js
file, we still have some work left to do though,
for example this view here with the title will later also hold the image and therefore this should be way
bigger than the row below it which will later just output some details.
Hence here, I will merge my meal row styles with another style object, so with the style set up in another
stylesheet object which I'll name meal header or whatever you want to name it and the same down there
by the way for the details in the end, there
I will merge this with styles meal detail, so that we have combined styles and let's start with the meal
header which we can set up here.
The meal header in the end will hold the image and also the title and I want the height of this to be
let's say 80% of the available height,
so this should be very very large. The meal details automatically will therefore get the remaining 20%
obviously and to see whether that works, let's output some details here, so in that view here,
in that row below our title row,
I also want to have some text here and there I'll output
let's say props duration and then m thereafter, for minutes because m duration will be a number which
we treat as minutes.
We just need to pass in the duration from the category meals screen of course,
so when we use the meal item, besides passing in a title, I'll set the duration prop because we're now
expecting this on the meal item.
We get this from itemData.item which is our meal and there, we'll have a duration property because
our meals as defined in the model here do have a duration property
and indeed if you have a look at the dummy data, this here is your duration which is fed in.
If we save this,
now we see our duration down there and actually, we can still change that height here to even 90%,
should be higher than it was here,
that looks better
and of course you can experiment with this as well. In the meal detail row,
I also want to have some horizontal padding, so left and right of let's say 10 and justify my content
here with space between, keep in mind it's a row so this will justify it horizontally, so that when we
have multiple items, they will be nicely distributed there.
So we have 20 minutes, let's output more information there by adding another text and there, output
the complexity,
so here I'll output complexity and thereafter, I'll output
the affordability. Now we just need to pass in that data as well when creating our meal item.
So here besides duration, we pass in complexity which we get here,
itemData.item.complexity and affordability, that's of course
itemData.item.affordability,
like that and if we save this and let this re-render, now we see this output here. Still not super beautiful
and we can definitely enhance this but a nice start. Now simple and affordable or our complexity
and affordability therefore, that should be styled a bit differently. We know it will be text and therefore
I can use some Javascript functions or methods we have available on strings, I will simply use toUppercase
to convert it to uppercase entirely like this and now this should already look a bit nicer than
before. Now you can still tweak the styling here, I'll go with with this styling here for now and let's now
add a background image above.
So for this, we wanted a background image behind this title text and thankfully, React Native makes adding
such a background image really really simple. React Native ships with a built-in component, the image
background component which we can use to render an image in the background as you would imagine by
the name. You add it next to the component behind which you want to add it and you add it before that component,
so here I add image background and on image background like on the normal image, you set a source. Here my
source is a web image, so we pass in an object, if it would be a local image, you would use require and what
you learned about local images earlier in the course but here, it's a web image, so we pass an object with
a URI prop and there we use props image which is where I expect to get that URL in this
component so of course we'll have to make sure we pass in the URL on that prop. I'll also add some
styling here and that will be styles.bgImage which we're now going add to the stylesheet down there,
wherever you want, maybe here, doesn't really matter. An important thing here, you have to set width and
height because it's an image from the web and I will use them 100% for both because it should fill
the entire space it gets. Now we just have to make sure we pass in that image prop here in category meals
screen, so besides the title, here I also want to pass in itemData.item.imageUrl is the
name of it, you can see that in the model, imageUrl, so that's what we're passing in and we pass this
to the image prop because that's what we're expecting and what we're setting here in the meal item. And
if you now save that and let's mix things up and test this on Android, just takes a bit longer to load
which is why I typically use iOS here but now if we test this, we see our burger here. What we don't
see anymore is our title though. To show the title again, make sure that you actually wrap image background
around it, this is how you tell React Native which content should be inside above that background
image. So now with that, here's our title, not that easy to read and we'll fix that but it's there again.
So we're getting started with that recipe here, now let's make sure the title is a bit easier to see
by giving it a style here, styles title which we can now set up down there and I want to set a font family
of open sans
bold, makes sense since we register this font.
Give it a font size which we increase a little bit, maybe 22,
you can play around with that of course.
Give it a color of white to make it a bit easier to read and also assign a background color so that we
can always see it, even if the background image would be white,
in which case white text would be hard to read, by giving this an RGBA color which is a color that
has built-in transparency so to say and this is simply a black color which is a bit transparent
and now also add a little bit of padding here, padding vertical
of five should look good so that the background colored box here doesn't sit right on the edges of
the text that's inside of the box and padding horizontal of 12 maybe. With that we should always see our
title and actually, we can probably increase that transparency here,
decrease the opacity,
yes that looks a bit nicer
I think,
like this. And the only thing I want to do now is I want to move that title down at the bottom of this
image and therefore on the bgImage style which I have here,
I'll set justify content to flex end because the background image automatically acts as a flexbox
so to say, like a view, so we can justify our content in there
and now we have that title at the bottom.
We could now also center the text by going to the title here and adding text align center
and in case it's too long, too big,
besides of course shrinking the font size which I'll do a little bit to 20,
of course you can go to that text here where you output a title and set the number of lines to 1 and this
will ensure that the text is automatically shortened
if it's too large, like here for the salad with cherry tomatoes. We also see a strange effect here on
iOS where we have some extra background behind our text and not just the background colored box here.
That's because I applied my background color and so on effect directly on the text, to fix this we can
cut it from the title here and only set up the color and so on there and instead add a title container
here where we add this background color and so on and wrap this container around our title, so an extra
view we add here and it's quite normal in React Native to nest multiple such views and on that view,
we can now add style, styles title container and if we save that, we should get rid of that strange behavior
on iOS,
yes
now we don't have that extra box there, instead
we just have one background color and the same on Android.
So now this doesn't look too bad but I'm not entirely happy,
I'd like to center my details here vertically as well and give it a little bit more space I guess and
for that we can give the header maybe 85% of the height and on the meal detail here,
keep in mind that our flex direction is row because we're merging meal row and meal detail here and
therefore our cross axis is top to bottom,
so if we want to center vertically, that is the cross axis on which we need to center.
So here we can set align items which does the cross axis positioning to center and also change our
color here a little bit to a little bit of a nicer color,
this very light gray, #f5f5f5 might look a bit better,
yes it
definitely does.
Now to make sure that we do really center vertically, we just need to be more explicit about the height
our meal details should take,
we take 85% on the header, so on the detail here, we can set a height of 15%
obviously to take the rest, yes and I'd say this looks quite decent here,
certainly list items with which we can work here.
I'll now just add a little bit of a border radius because you know I like border radiuses, so I'll add
a border radius of 10 here so that we have some rounded corners and with that, if you go back, we're almost
there but you'll notice that the image actually doesn't respect the border radius.
Now to fix that, on the meal item, we just have to say overflow hidden so that no child item can go outside
of this space or this shape
we're building here.
And with that, that's a start, something we can work with,
now of course we want to make sure that when we tap such an item, we actually go to the detail page.