Now that we got the basics about navigation down, that we're able to pass data around,
let's take a step back and focus on the app we're building which is of course not looking that great
and let's focus on these category items here in the grid.
We can tap them but obviously this is not an app
you would like to use. Now to make that more usable in the categories screen here,
I'll actually grab this item here,
this touchable opacity, so this grid item and outsource this into a separate component, not something you
must do but something you might want to consider doing simply to keep your components leaner and cleaner.
For that in the components folder, I'll add a CategoryGridTile.js file, the name is of course totally
up to you and in there, we need to import React from React, we'll certainly also need some stuff from
React Native to build a component in there, namely we'll need touchable opacity of course, we'll need
the view, we'll need text and we'll need a stylesheet so that we can also style this here and now we can
create the category
grid tile component here which receives some props. We will need a stylesheet here which I'll store
in the styles constant and of course as always, we can thereafter export the component and inside of
this component function, I'll return the jsx code I just cut out of the categories screen
here. So in here, the touchable opacity set up, this grid item is set up but we'll have to change a couple
of things. In the categories screen for example, I'm setting up the grid item style here. Now we could leave
it here and kind of pass it into our grid tile and then merge it together there as you learned it but
I will simply set up all the styling in the component itself because we'll only use the category grid
tile in the grid on the categories screen. So I'll add the grid item style here to the stylesheet
in this file,
hence this works again, the onPress handler will not work yet, we'll fix this soon and now we can go
back to the categories screen and of course, import our component. So import the category grid tile component
there from the components folder and there,
category grid tile and now simply return this here when we render a new item.
Now of course like this it won't work,
we need to forward some data into the grid tile for it to work correctly there and we also need to make
sure that pressing this does navigate us. Now for that, I'll pass in the data which we need there which
is the title, so that's itemData.item.title and that's now a prop we can use in the category
grid tile and I also want to pass in another prop which passes in a function which we then can execute
to navigate and I'll name this onSelect but you can name this whatever you want and in there, I just want
to execute the code which I currently execute in onPress. So I'll cut this from here out of the category
grid tile, move this back into the categories screen, into this function I pass to onSelect and now all
we have to do is trigger onSelect from inside the category grid tile, that's of course a normal pattern
you'd know from React. So back in the category grid tile, onPress can simply point at props onSelect
to trigger the function that's passed in the onSelect prop.
Now the title I'm outputting here also can just be props.title
because we're getting this title prop as a prop on our category grid tile we're passing it here.
With that, we split our component a little bit but of course now I also want to work on the styling a
bit more. So back in the category grid tile, I for example want to use the color I'm setting up because
every category gets a color stored in that color property here,
so it would be nice to use that. Hence we can forward the category grid tile as well, forward color
here, you can of course name this prop whatever you want on the item.color property
and here, it has to be .color because we named the property color here in the model and now in a category
grid tile, we can use that color to style this here.
So how do then style this, how should this look like? By adding a style to the view we have inside of
the touchable opacity because the touchable opacity component itself is invisible but the view
isn't and there, we can pass in an object and set the background color here
to props.color.
Well let's see how that looks like, if we save that and we wait for this to reload,
doesn't look too bad but it's too small,
it should fill out the entire grid item and not just the row with the text in there.
So to improve that, I'll actually have this inline style here but I'll merge this together into a surrounding
object with another styling configuration which I set up in the stylesheet and I'll name this container,
you can name it whatever you want,
styles container,
pull out all the key-value pairs in there as well so that we merge these styles here and now, container
is a stylesheet object we can add down there and in here, we can set flex one to make sure that every
item fills out all the space it gets and now this looks way better.
Now I'm still not 100% happy,
I want to add a little bit of a border radius here, let's say of 10 to have some rounded corners
and of course, you can set up any styling you want here, you prefer,
I will also set up a shadow color of black and a shadow opacity of .26 and a shadow offset of
width 0, height 2 and a shadow radius of 10 and an elevation of 3, elevation for Android
if you remember because these shadow properties only affect iOS, so that we get a little bit of this
three-dimensional card look and of course as I mentioned, you can style this in whichever way you want.
Now in addition, I want to make sure that this text here sits in the bottom right corner and has a little
bit of padding around it
of course, a little bit of spacing around it. So I'll add a little bit of padding here,
let's say of 10 and now set justify content to flex-end, the flex direction in the container of course
is top to bottom because it's column, so flex end will move this to the bottom here and now to also
move it to the right on the horizontal axis,
I set align items to flex end as well and this moves that to the end of the cross axis which is left
to right in a normal view where you didn't change the flex direction. With that, we get this look which
I'd say is better but of course, the text here, the text styling could also change and a little bit
more padding might look good,
maybe 15 but of course we can experiment with that and also one important side note, in this app I'll
not focus on building a totally responsive experience here,
I'll try to keep this short and concise because the main focus of this module of course is navigation,
hence I'll not optimize this for all possible screens and platforms.
This is something you can of course do as a practice,
I'll not do adhere to not unnecessarily bloat this module, so I'll just set up some styling that looks
good on these emulators.
That being said, a little bit more padding might make sense and I also want to style the title here,
hence I'll add let's say title style here,
set up in the stylesheet,
let's add it here and there,
I want to use my font family, open sans bold which I can use of course because I'm registering it here
in app.js, so open sans bold is added now here and maybe also change the font size a little
bit to 22. We save
this, this looks quite decent.
Now there's one last thing which I want to do
on my category grid tile, on the text here, I'll set the number of lines to 2 so that any text that would
be longer than that actually just gets cut off which I think looks a bit nicer. And last but not least,
you might notice that on Android for light and lovely, this is on the left here because it's broken
into two lines, to make sure that this is also on the right, on the title here,
I'll set text align to right to force this to be on the right.
So let's wait for that to reload
and now that's looking the way it should.
Now that's not too bad here,
now you might notice that the effect looks a bit strange if I tap an item here, we get this strange extra
border around it.
Now one thing I will still do here which is totally optional but still, I'll add it here, I'll add the platform
API and also add touchable native feedback to actually use the ripple effect instead of touchable opacity
if supported.
So here, I'll have my touchable component which by default is touchable opacity
but if platform.os equals Android and as you learned earlier in the course, the version is greater
or equal than 21, then we know that touchable native feedback is supported,
so then I'll set touchable component equal to touchable native feedback, like this.
Use touchable component here instead of touchable opacity
and with that, we should have a nice ripple effect on Android, on iOS
we have the opacity effect which we want
and on Android, we now have a ripple effect
but styling is off now.
This however is something we can fix by adding an extra view around this which receives our grid items
style instead of the touchable component here
and with that, we just need to add one extra style property on the touchable component and set flex
one.
I'm doing it with an inline style here
quick and dirty, you could add a separate style in the stylesheet. With that it looks and feels the same
on iOS
and now also on Android, ripple effect is there.
Now it's not using our rounded corners though, instead it renders a square or a rectangle
and you also learned earlier how to fix that. To fix it,
all we have to do is on the grid item, we add the border radius of 10
and then we actually add overflow hidden to make sure that child items can't be rendered outside of
that wrapping view
which means that the ripple effect can't go outside of that rounded box.
Now we have that look and that's the one adjustment I want to make here for different platforms
and with that, that doesn't look too bad I'd say.
Now of course, you can tweak the look of that, you can tweak the font size and so on, make that look really
good on your devices you you're testing.
I'm happy with this look and now it's really time to also render some recipes
when we select a category here.