1 00:00:02,290 --> 00:00:09,430 So now that the general game logic works, let's focus more on finishing up that styling 2 00:00:09,700 --> 00:00:16,180 and also on adding our own custom fonts and a nice little image on the game over screen because working 3 00:00:16,180 --> 00:00:23,530 with images and working with custom fonts is a typical thing in modern app development of course, you 4 00:00:23,530 --> 00:00:30,520 rarely want to stick to the default system fonts and rarely do you have an app without any images. 5 00:00:30,520 --> 00:00:37,390 So therefore let's get started with custom fonts and in a React Native expo, adding fonts is super trivial. 6 00:00:38,200 --> 00:00:40,820 In your project folder, in the assets folder, 7 00:00:40,870 --> 00:00:47,000 let's create a fonts folder. You can store that anywhere though 8 00:00:47,050 --> 00:00:52,560 but I like to keep it in the assets folder to keep my assets like fonts and images organized. 9 00:00:53,080 --> 00:00:58,270 So here in the fonts folder, I unsurprisingly want to manage my fonts and for that, attached you find 10 00:00:58,270 --> 00:01:03,460 a zip file with two fonts which you can just extract and then drag and drop into here, 11 00:01:03,560 --> 00:01:06,730 that's OpenSans-Bold and OpenSans-Regular, 12 00:01:06,730 --> 00:01:12,790 so these two fonts are attached to this video in a zip file, extracted and drag them into the fonts 13 00:01:12,790 --> 00:01:14,100 folder. 14 00:01:14,110 --> 00:01:22,390 Now with that, these fonts are generally available but to use them, you still need to configure more. 15 00:01:22,460 --> 00:01:29,780 You need to go to your app.js file and basically instruct React Native and expo to load these fonts, 16 00:01:29,810 --> 00:01:37,920 so to use them. For that in the app.js file and I'm using the app.js file because that's the first 17 00:01:38,010 --> 00:01:43,560 file which is loaded or which is executed so to say when the app starts and you want to load your fonts 18 00:01:43,590 --> 00:01:51,060 when the app starts, in there, you need to add an import and that import is that you import everything as 19 00:01:51,060 --> 00:01:58,630 font, though that name here is up to you but typically, you use font here, from expo-font. 20 00:01:59,140 --> 00:02:07,380 So expo-font is a package which gives you font utilities, so utilities that allow you to load fonts 21 00:02:07,800 --> 00:02:13,140 and you import everything from that package and bundle it together in this font object, 22 00:02:13,140 --> 00:02:15,800 that's what we're doing here. Now 23 00:02:15,950 --> 00:02:21,920 to load fonts, I'll add a new function outside of the functional component because this function doesn't 24 00:02:21,920 --> 00:02:26,580 need to be recreated for every component rerender cycle. 25 00:02:26,610 --> 00:02:27,860 Now I'll name it fetch fonts, 26 00:02:27,870 --> 00:02:29,060 the name is up to you 27 00:02:29,330 --> 00:02:31,190 and in this function here, 28 00:02:34,010 --> 00:02:38,640 I will call font.loadAsync. 29 00:02:38,710 --> 00:02:43,810 Now this is a function that or a method on the font package which we're importing here that allows you 30 00:02:43,810 --> 00:02:52,050 to load fonts and what you pass to load async is an object where you tell Expo and therefore React Native 31 00:02:52,120 --> 00:02:57,010 about all the fonts you want to load. You do this by using a key where you pick any name of your choice, 32 00:02:57,310 --> 00:03:02,710 like open-sans and you'll later be able to use these fonts by these names, 33 00:03:02,710 --> 00:03:06,400 so here open sans because my font is called open sans. 34 00:03:06,400 --> 00:03:10,510 So here it's open sans and then you add require, 35 00:03:10,840 --> 00:03:17,180 that's a language feature Javascript offers where you point at the path where this font is stored. 36 00:03:17,200 --> 00:03:18,310 That's a relative path, 37 00:03:18,340 --> 00:03:20,820 so here I point at the assets folder, 38 00:03:20,850 --> 00:03:28,760 the fonts folder and then it's the OpenSans-Bold, not bold but regular.ttf file and now 39 00:03:28,760 --> 00:03:36,210 I'll add a second item here to this object I pass to load async and that could be open-sans-bold. 40 00:03:36,210 --> 00:03:40,660 Now these names are totally up to you and there I want to load the bold version. 41 00:03:41,290 --> 00:03:48,160 So with that, we're telling React Native in the end where our fonts live, where these font files live and 42 00:03:48,160 --> 00:03:56,650 to which names we want to map them and we can later use these names to assign these fonts to text. Now 43 00:03:56,770 --> 00:04:03,550 load async actually returns a promise, which means that this will take a bit longer, not super long but 44 00:04:03,550 --> 00:04:09,360 it will not load these instantaneously and I will return this promise here inside of fetch fonts so 45 00:04:09,360 --> 00:04:15,600 that whenever we call fetch fonts, we can wait for this promise to resolve before we continue. Now where 46 00:04:15,600 --> 00:04:19,610 do we want to fetch our fonts though? 47 00:04:19,670 --> 00:04:26,720 Well we could manually load our fonts here, we could for example call fetch fonts like this and it would 48 00:04:26,720 --> 00:04:28,180 go ahead and fetch our fonts 49 00:04:28,190 --> 00:04:34,220 but the problem is, we would continue rendering and we would eventually render our content and if anywhere 50 00:04:34,220 --> 00:04:38,190 in the content, we use text that tries to use such a font, 51 00:04:38,300 --> 00:04:43,850 if the font hasn't been loaded yet and as I said, it will take only a couple of milliseconds but still 52 00:04:43,850 --> 00:04:50,660 for the first render cycle, the font might not have been loaded, then we would get an error. So loading 53 00:04:50,660 --> 00:04:55,400 our fonts like this is not recommended, it will very likely not work. 54 00:04:55,430 --> 00:05:03,310 Instead there is a special component which you can use, it helps you load your fonts. You import this 55 00:05:03,310 --> 00:05:10,450 component from expo and the name of that component is AppLoading. 56 00:05:10,460 --> 00:05:17,480 Now that's a component which will basically prolong the default loading screen, the splash screen users 57 00:05:17,570 --> 00:05:24,860 see anyways when the app is launching, it will prolong this screen to stay active until a certain task 58 00:05:24,860 --> 00:05:26,150 of your choice is done, 59 00:05:26,150 --> 00:05:29,610 like for example until fetching fonts is done. 60 00:05:29,960 --> 00:05:35,180 So AppLoading it is, in the app component, 61 00:05:35,190 --> 00:05:41,520 we just have to make sure now that we render this component instead of our actual content as long as 62 00:05:41,520 --> 00:05:43,650 we haven't loaded our fonts yet 63 00:05:43,740 --> 00:05:49,000 or as long as we're not done with loading whatever we wanted to load. 64 00:05:49,120 --> 00:05:55,390 Now the cool thing is, we can use state for that and start with an initial value of false because the 65 00:05:55,390 --> 00:06:04,240 state I want to manage here is data loaded or whatever you want to call it and set data loaded. 66 00:06:04,350 --> 00:06:11,880 Now here, I want to check if data loaded is not true, hence the exclamation mark, then I know the data 67 00:06:11,880 --> 00:06:16,760 hasn't been loaded yet and that's the case initially and in this case, I'll not even continue with my 68 00:06:16,920 --> 00:06:17,580 other logic, 69 00:06:17,640 --> 00:06:25,170 instead for this functional component, I'll immediately return the AppLoading component as the content 70 00:06:25,170 --> 00:06:25,610 of the app 71 00:06:25,620 --> 00:06:32,340 basically because I don't want to render any other content if we're still loading our data. Now AppLoading 72 00:06:32,340 --> 00:06:40,740 is a component coming from Expo which takes a start async prop where we point at the operation we want 73 00:06:40,740 --> 00:06:46,200 to start when this is first rendered and that's of course our fetch fonts function. 74 00:06:46,200 --> 00:06:49,480 So here, I'm pointing at fetch fonts, at this function. 75 00:06:49,500 --> 00:06:51,290 Now important, a) 76 00:06:51,630 --> 00:06:57,420 this has to be a function which you pass here and b) it has to be a function that returns a promise because 77 00:06:57,700 --> 00:07:01,980 expo will automatically listen to that promise for you 78 00:07:01,980 --> 00:07:09,240 and when the promise resolves, it will know that the loading is done and it will then call whatever you 79 00:07:09,240 --> 00:07:10,770 pass here to onFinish. 80 00:07:10,770 --> 00:07:17,530 So here, you need to pass a function which then actually sets data loaded to true. 81 00:07:17,610 --> 00:07:23,160 So this function here will be executed for you when this operation is done and for expo to find out 82 00:07:23,160 --> 00:07:24,120 when this is done, 83 00:07:24,120 --> 00:07:27,360 this should return a promise. 84 00:07:27,380 --> 00:07:33,760 So now these two props will work together and we're updating data loaded, this state to be true and therefore 85 00:07:33,760 --> 00:07:39,410 to not render this content but to proceed with executing this code and eventually rendering the 86 00:07:39,410 --> 00:07:40,760 content down there 87 00:07:41,060 --> 00:07:47,810 when fetching our fonts is done and you could do any async operation here but typically, you use AppLoading 88 00:07:47,810 --> 00:07:50,690 to load some assets, like fonts or anything like that, 89 00:07:50,750 --> 00:07:56,030 so assets that should be there when the app starts which you need immediately and typically that are 90 00:07:56,030 --> 00:07:57,770 fonts. 91 00:07:57,870 --> 00:08:05,710 Now you can also add an onError handler here by the way and here, I'll just console log the error object 92 00:08:05,710 --> 00:08:07,050 which we also get here 93 00:08:07,300 --> 00:08:14,470 in cases where loading that fails. Of course, you might not just want to log this but instead, do something 94 00:08:14,470 --> 00:08:16,570 else, show some alternative content in your app, 95 00:08:16,570 --> 00:08:20,230 anything like that. Here I'll just log it because this shouldn't fail, 96 00:08:20,230 --> 00:08:25,710 the fonts are available locally here so that should be loadable without issues. 97 00:08:25,760 --> 00:08:31,330 Now if we save that, our app of course restarts and we see no difference here, 98 00:08:31,400 --> 00:08:36,380 our loading screen also doesn't really take longer as before because that loading is super fast, 99 00:08:36,380 --> 00:08:37,820 it just doesn't happen instantly, 100 00:08:37,820 --> 00:08:39,830 that is why we needed this approach. 101 00:08:39,830 --> 00:08:41,240 But now we loaded the fonts, 102 00:08:41,240 --> 00:08:43,440 how can we now use them? 103 00:08:43,460 --> 00:08:48,980 Well let's say we want to change our start a new game title here to use our font. Now for that, 104 00:08:48,980 --> 00:08:57,390 we need to go to the start game screen which is where this title lives in the end, here, start a new game, 105 00:08:57,390 --> 00:09:03,540 it does have the title style and therefore down in the stylesheet here on title, we can now set font family 106 00:09:03,630 --> 00:09:08,050 to change the font family and set this to open-sans-bold 107 00:09:08,050 --> 00:09:09,270 for example 108 00:09:09,270 --> 00:09:15,180 and of course the identifier you use here has to be an identifier you loaded here. 109 00:09:15,210 --> 00:09:17,800 So here, I have open-sans-bold and open sans, 110 00:09:17,850 --> 00:09:25,180 I can use these two identifiers in my code anywhere in the app when I want to assign a custom font and 111 00:09:25,180 --> 00:09:27,240 that's just what I'm doing here. 112 00:09:27,240 --> 00:09:32,940 Now you see, that has a different font that is bold and by the way, if you're using custom fonts and you 113 00:09:32,940 --> 00:09:36,180 want a bold font, you have to load it with the font family, 114 00:09:36,180 --> 00:09:42,180 you can't set the font weight. React Native supports this but for custom fonts, expo at the moment doesn't 115 00:09:42,180 --> 00:09:42,840 support this, 116 00:09:42,840 --> 00:09:47,790 instead you simply have to use a separate font family which isn't really a problem as you can see.