0 1 00:00:00,730 --> 00:00:07,870 Hey, guys. In this lesson, we're going to be looking at more complex layouts and using SwiftUI to create 1 2 00:00:07,870 --> 00:00:08,930 those. 2 3 00:00:09,010 --> 00:00:13,210 In addition, we're going to be using some custom fonts that we're going to download off the Internet 3 4 00:00:13,720 --> 00:00:18,050 and we're also going to be working with RGB colors and HEX codes. 4 5 00:00:18,070 --> 00:00:23,500 Finally, I'm going to show you how to tap into thousands of images that Apple has designed for us to 5 6 00:00:23,500 --> 00:00:26,900 use through SF symbols in SwiftUI. 6 7 00:00:27,070 --> 00:00:33,160 And we're going to be looking at how we can easily extract this Subviews that we've created in SwiftUI 7 8 00:00:33,460 --> 00:00:38,410 to be reused in other projects and other screens. 8 9 00:00:38,410 --> 00:00:40,960 So let's get started. In this lesson, 9 10 00:00:40,960 --> 00:00:47,950 we're going to be extending our SwiftUI knowledge and we're going to be building a really beautiful 10 11 00:00:48,010 --> 00:00:51,930 Stack View enabled personal business card app. 11 12 00:00:52,360 --> 00:00:57,970 So by the end of the lesson, you will have learned how to embed views within other views using SwiftUI 12 13 00:00:57,970 --> 00:01:04,750 as well as a bunch of advance layout techniques to create your business card in a beautiful app that 13 14 00:01:04,750 --> 00:01:08,830 you get your clients to download when they want your details. 14 15 00:01:08,830 --> 00:01:16,930 So get started by creating a new Single View App. And I'm going to call it AngelaCard. But, of course, 15 16 00:01:16,990 --> 00:01:19,270 you can call it whatever you want it to. 16 17 00:01:19,300 --> 00:01:22,630 This is going to be your business card on the App Store. 17 18 00:01:22,640 --> 00:01:28,900 Now, make sure that the user interface is again selected as SwiftUI, and then go ahead and create and 18 19 00:01:28,900 --> 00:01:31,760 save your project. 19 20 00:01:31,820 --> 00:01:36,650 So the first thing I'm going to do is go ahead and create some space for myself. 20 21 00:01:36,830 --> 00:01:42,890 I find that I like to have at least a third of the screen taken up by the preview so that I can see what's 21 22 00:01:42,890 --> 00:01:46,280 going on. All right. 22 23 00:01:46,280 --> 00:01:50,330 So the first step is adding a background color to our app. 23 24 00:01:50,870 --> 00:01:52,760 So here's a challenge for you. 24 25 00:01:52,790 --> 00:01:59,510 Can you remember how to use the Z stack to add a background color and make sure that the color goes 25 26 00:01:59,510 --> 00:02:03,160 beyond the safe areas to cover the entire screen. 26 27 00:02:03,200 --> 00:02:06,310 So if successful, this is what you should end up with. 27 28 00:02:06,320 --> 00:02:09,710 You don't need to change the text element, just the background color. 28 29 00:02:09,800 --> 00:02:15,780 So pause the video and try to complete this challenge. 29 30 00:02:16,020 --> 00:02:16,290 All right. 30 31 00:02:16,320 --> 00:02:22,420 So the first thing that we need to do is to create a Z stack, a stack that allows us to put things one 31 32 00:02:22,420 --> 00:02:26,530 on top of each other all the way from the back of the phone to the front of the phone. 32 33 00:02:26,560 --> 00:02:33,130 So let's go ahead and go into our Object library, drag a Z stack into our code, and then I'm going to 33 34 00:02:33,130 --> 00:02:40,480 replace that text placeholder with the text that we've really got. Now that I've got a Z stack right 34 35 00:02:40,480 --> 00:02:42,100 at the very top of the stack, 35 36 00:02:42,100 --> 00:02:48,960 I'm going to add a color element. And this color is going to be set to green in my case. 36 37 00:02:48,960 --> 00:02:55,930 And in order to make sure that the color goes beyond the safe areas, I'm going to add a modifier which 37 38 00:02:55,930 --> 00:02:59,960 is the one that's the edgesIgnoringSafeAreaModifier, 38 39 00:03:00,310 --> 00:03:02,920 and we want that to go to all four sides. 39 40 00:03:02,920 --> 00:03:04,660 That's it. 40 41 00:03:04,870 --> 00:03:11,740 Now, I recommend formatting these modifiers, so that they actually go below the actual component because 41 42 00:03:11,740 --> 00:03:13,660 you often have quite a few of them. 42 43 00:03:13,930 --> 00:03:20,620 But at the moment, this color looks kind of ugly. And I know that there are quite a few that you can choose 43 44 00:03:20,620 --> 00:03:21,150 from. 44 45 00:03:21,280 --> 00:03:28,840 But what if we wanted a custom color? How would we do that? Now, one of my favorite places for finding 45 46 00:03:28,870 --> 00:03:33,430 a beautiful color palette is a tool called flatuicolors,com. 46 47 00:03:33,430 --> 00:03:39,370 And here, you can see professionally design beautiful colors that are optimized for iOS display. 47 48 00:03:39,940 --> 00:03:41,980 So here, I'm going to choose one of these colors, 48 49 00:03:41,980 --> 00:03:45,420 maybe the green sea color, and I'm going to click copy. 49 50 00:03:45,850 --> 00:03:48,730 This is copied in a HEX code format. 50 51 00:03:48,730 --> 00:03:51,420 So this is a hexadecimal code. 51 52 00:03:51,610 --> 00:03:54,500 And in iOS when we create a color, 52 53 00:03:54,640 --> 00:04:00,750 the easiest way to create a custom color is through specifying the RGB values. 53 54 00:04:00,970 --> 00:04:04,380 And they're expecting a doubles or a decimal place here. 54 55 00:04:04,600 --> 00:04:13,540 And each of these colors, red, green, or blue expects a value between 0 and 1. And 1 would be a full bar 55 56 00:04:13,540 --> 00:04:15,780 of that color and 0 would be none. 56 57 00:04:15,790 --> 00:04:19,510 So for example, if I had a red: 1, green: 0, blue: 0, 57 58 00:04:19,510 --> 00:04:21,660 it would just be the color red. 58 59 00:04:22,210 --> 00:04:28,050 And depending on the mix of these three colors, we can create all sorts of colors. 59 60 00:04:28,060 --> 00:04:31,600 Previously, I've got my copied hexadecimal color code. 60 61 00:04:31,600 --> 00:04:37,960 And if you go to a place called your uicolor.xyz, then you can actually convert your hex color 61 62 00:04:38,230 --> 00:04:40,080 to a UIColor. 62 63 00:04:40,300 --> 00:04:43,700 And it shows you the components that you have to add. 63 64 00:04:43,720 --> 00:04:48,350 So I'm going to go ahead and copy this color right at the bottom, 64 65 00:04:48,430 --> 00:04:53,890 everything inside the parentheses. And then back over here, I'm going to paste it in here. 65 66 00:04:54,340 --> 00:05:01,300 And you'll notice that the SwiftUI way of initializing colors is a little bit different from 66 67 00:05:01,330 --> 00:05:02,230 the UIColor. 67 68 00:05:02,230 --> 00:05:06,850 So the last property, instead of being called Alpha, it's actually called opacity. 68 69 00:05:06,850 --> 00:05:10,450 And in fact, this last component is completely optional. 69 70 00:05:10,450 --> 00:05:11,910 We don't even need to include it. 70 71 00:05:12,070 --> 00:05:17,980 But however, if you wanted to add transparencies, so if you wanted to make it half as opaque, then you 71 72 00:05:17,980 --> 00:05:19,900 could change that property. 72 73 00:05:19,900 --> 00:05:25,960 But in our case, we don't need to, we want it fully opaque. And we have this beautiful green sea color. 73 74 00:05:27,130 --> 00:05:30,190 So I want this piece of text to say my name. 74 75 00:05:30,220 --> 00:05:33,720 So it's a business card after all, they need to know what I'm called. 75 76 00:05:34,000 --> 00:05:38,230 And now I'm going to modify my text. 76 77 00:05:38,230 --> 00:05:43,780 And, again, I'm going to go to my modifiers and I'm going to search for the text related modifiers. 77 78 00:05:44,170 --> 00:05:51,700 So I'm going to go ahead and change the font of my text and I'll change it to a title font, and then 78 79 00:05:51,700 --> 00:06:03,140 maybe I'll make the text bold. And also maybe we can change the foreground color as well. So these are 79 80 00:06:03,230 --> 00:06:04,600 three attributes. 80 81 00:06:04,640 --> 00:06:06,670 It's pretty easy to do. 81 82 00:06:06,830 --> 00:06:08,950 Let's change that to white. 82 83 00:06:08,990 --> 00:06:12,830 So now I have a piece of text that says my name. 83 84 00:06:12,950 --> 00:06:16,400 It's a large title sized font. 84 85 00:06:16,460 --> 00:06:18,870 It's bold and it's white. 85 86 00:06:18,890 --> 00:06:27,260 Now, what if I wanted to be able to add a custom font, so something that isn't already inbuilt to Xcode? 86 87 00:06:27,500 --> 00:06:34,700 Well, a really easy way of doing that is downloading a free for commercial use font from Google, and Google 87 88 00:06:34,700 --> 00:06:40,610 fonts have loads of beautiful typefaces that you can choose from. The one that I have had my eye on is 88 89 00:06:40,610 --> 00:06:42,190 something called Pacifico. 89 90 00:06:42,650 --> 00:06:49,490 So once I found it, I'm going to click plus. And now that I've got this family selected, and I can go ahead 90 91 00:06:49,580 --> 00:06:50,810 and download it. 91 92 00:06:51,630 --> 00:06:58,580 So, now there it is in my Downloads folder, so I can double click on it to unzip and expand. 92 93 00:06:58,580 --> 00:07:04,770 And now I have my actual font file which is the Pacifico-Regular.ttf. 93 94 00:07:04,880 --> 00:07:13,730 So, now I'm going to go into Xcode and popping open the left-hand, pane I'm going to create a new group. 94 95 00:07:13,730 --> 00:07:15,920 So this group is going to be called fonts. 95 96 00:07:15,920 --> 00:07:21,020 And right now, I only have one font, but maybe in the future, maybe I'll have more. 96 97 00:07:21,020 --> 00:07:28,070 So here, I'm going to drag this Pacifico-Regular into my fonts folder, and then making sure that you select 97 98 00:07:28,220 --> 00:07:32,480 Add to targets to be able to use it in this app. 98 99 00:07:32,480 --> 00:07:41,750 So, now we've got Pacifico-Regular loaded into our project, we can go over now to our LaunchScreen.storyboard. 99 100 00:07:41,810 --> 00:07:49,820 So this is our usual Interface Builder storyboard file and I'm just going to add a UILabel in here, 100 101 00:07:50,690 --> 00:07:59,710 just so that I can take a look at the attributes and change the font from system to custom. 101 102 00:07:59,840 --> 00:08:05,150 And then in the family dropdown, I'm going to scroll down just to check and make sure that I've actually 102 103 00:08:05,150 --> 00:08:07,970 got Pacifico loaded and ready. 103 104 00:08:07,970 --> 00:08:14,360 So, now that I've assured myself that I can actually load my custom font, I can now delete it and go back 104 105 00:08:14,360 --> 00:08:24,440 to my ContentView. And here, instead of using the default system font in here, I'm going to load a custom 105 106 00:08:24,440 --> 00:08:34,250 font. And we do that by creating a new font object, and then writing .custom to create a custom fonts. 106 107 00:08:34,880 --> 00:08:36,860 And then we have to give it a name. 107 108 00:08:36,950 --> 00:08:41,280 But it's not enough to simply just write the name of the file, 108 109 00:08:41,420 --> 00:08:53,210 Pacifico-Regular. You can see that if I try to add in the font, custom, and add a size, when 109 110 00:08:53,210 --> 00:08:59,390 you try to preview it, it won't actually change the font size, even though we've seen previously that 110 111 00:08:59,390 --> 00:09:03,320 we've definitely incorporated it into our project. 111 112 00:09:03,320 --> 00:09:04,730 So what's going on? 112 113 00:09:04,730 --> 00:09:12,500 Well, we actually have to change the project settings through our Info.plist file. So remember, these 113 114 00:09:12,500 --> 00:09:17,480 are the property list items where we can specify the settings for our project. 114 115 00:09:17,480 --> 00:09:23,840 So here we have to click on the add button and search for something called Font with a capital "F," 115 116 00:09:23,930 --> 00:09:27,290 we find this one called Fonts provided by application. 116 117 00:09:29,930 --> 00:09:33,210 And this should be an array of items. 117 118 00:09:33,210 --> 00:09:40,230 So in here under item one, you're going to go ahead and add in the name of your new font file, 118 119 00:09:40,260 --> 00:09:47,990 so it's called Pacifico-Regular, and make sure that you add in the font format as well, 119 120 00:09:48,150 --> 00:09:54,810 so it's a .ttf. And then hit enter and check that you haven't made any typos in there. 120 121 00:09:55,230 --> 00:10:03,820 And now, we can go back to our ContentView. And once we refresh our screen, you'll see that it's now able 121 122 00:10:03,820 --> 00:10:11,240 to load up that file and use it in our font for our text. 122 123 00:10:11,340 --> 00:10:14,560 Now, let's continue building out our app. 123 124 00:10:14,580 --> 00:10:17,970 Now, I want to have a bunch of items stacked vertically. 124 125 00:10:17,970 --> 00:10:24,700 So what better than using a VStack. And the VStack is going to be a whole bunch of components. 125 126 00:10:24,720 --> 00:10:30,500 And right now, I've only got one thing that needs to go in the stack which is my Text object. So I'm going 126 127 00:10:30,500 --> 00:10:35,530 to hold down the command key on my keyboard and I'm going to select this Text object. 127 128 00:10:35,760 --> 00:10:43,110 And once I click on it, you can see an extended menu of all the things that we can do to this component. 128 129 00:10:43,110 --> 00:10:47,810 But in my case, I'm just going to embed it in a vertical stack. 129 130 00:10:48,060 --> 00:10:55,730 Now that I've got my vertical stack ready, I'm going to go and add some other components to it. 130 131 00:10:55,770 --> 00:11:00,540 I want to add another text item just below it in the stack. 131 132 00:11:00,540 --> 00:11:06,960 And I find that when I'm dragging and dropping it onto the interface directly, it's actually really fiddly 132 133 00:11:06,960 --> 00:11:13,920 to try and get it to do exactly what I want which is to go just below this current text component. 133 134 00:11:14,280 --> 00:11:17,910 So I find it easier dragging and dropping it straight into my code here like so. 134 135 00:11:17,910 --> 00:11:24,100 This piece of text is going to be my job title. 135 136 00:11:24,100 --> 00:11:35,750 So let's say, it's "iOS Developer." And then we're going to modify this text a little bit. And the modifications 136 137 00:11:35,750 --> 00:11:43,820 I'm going to add is I'm going to change the foreground color of my text to maybe, again. white. 137 138 00:11:44,120 --> 00:11:49,060 And I'm also going to change the font of this text. 138 139 00:11:49,500 --> 00:11:51,610 So let's drag that on as well. 139 140 00:11:51,710 --> 00:11:59,180 And in this case, I'm going to keep the system font, but I'm going to change this to a different font 140 141 00:11:59,180 --> 00:11:59,800 size. 141 142 00:12:00,050 --> 00:12:04,670 So I'm going to select the system with a size of 25. 142 143 00:12:05,240 --> 00:12:11,210 So it's a little bit smaller than the big title, but it should be large enough to be easily visible. 143 144 00:12:12,840 --> 00:12:19,830 Now, on top of my VStack right at the top, I want to add an image of myself, so that they'll be able to 144 145 00:12:19,830 --> 00:12:21,140 know who I am. 145 146 00:12:21,140 --> 00:12:25,470 They'll be able look at the app, look at me, and assure themselves that it's the same person. 146 147 00:12:26,100 --> 00:12:30,240 So I'm going to go ahead and find a image of myself, 147 148 00:12:30,240 --> 00:12:32,370 and here's one that's relatively recent. 148 149 00:12:32,370 --> 00:12:38,770 So let's go ahead and save this image and I'm just going to save it as my name Angela. 149 150 00:12:38,880 --> 00:12:46,080 Now, I can go into my Assets folder and drag that image into my assets and I'm going to make a note of 150 151 00:12:46,110 --> 00:12:47,610 what I've named that file. 151 152 00:12:47,610 --> 00:12:49,260 So it's called Angela. 152 153 00:12:49,260 --> 00:12:55,290 Now in your case, you might have a image of yourself lying somewhere on your computer or on a digital 153 154 00:12:55,290 --> 00:12:56,070 camera, 154 155 00:12:56,130 --> 00:12:59,910 go ahead and drag it in and give it your own name. 155 156 00:13:00,360 --> 00:13:10,060 And once you've done that, we can come back and resume our preview, and then go into our library and find 156 157 00:13:10,150 --> 00:13:12,200 a image object. 157 158 00:13:12,400 --> 00:13:19,310 And I'm going to drag that image right at the top of my VStack like so. 158 159 00:13:19,330 --> 00:13:23,140 So the image name, well, at least my image name was called Angela. 159 160 00:13:23,140 --> 00:13:25,210 Yours might be called something else. 160 161 00:13:25,210 --> 00:13:31,390 But once we've done that, it should load in the image at its original size. So it might be too large or 161 162 00:13:31,390 --> 00:13:33,120 it might be too small. 162 163 00:13:33,130 --> 00:13:35,380 So how can we resize it? 163 164 00:13:35,380 --> 00:13:38,760 Well, we have to first make it resizable. 164 165 00:13:38,830 --> 00:13:41,330 So that's one of the modifiers. 165 166 00:13:41,560 --> 00:13:49,510 And if we search for it, we should be able to find image resizable which is what I'm going to drop onto 166 167 00:13:49,540 --> 00:13:51,770 my image component. 167 168 00:13:52,480 --> 00:13:59,920 And then you can see that it's going to stretch to fill all the available space now, which is not what 168 169 00:13:59,920 --> 00:14:00,280 I want, 169 170 00:14:00,430 --> 00:14:04,170 and I definitely don't want to be stretched to look like a stick. 170 171 00:14:04,180 --> 00:14:11,080 So instead, I'm going to go and find something called aspect ratio. 171 172 00:14:11,800 --> 00:14:19,410 So this is going to allow me to define the aspect ratio of the image and the content mode. 172 173 00:14:19,480 --> 00:14:25,810 So instead of trying to fill all the available space, I'm going to change it to fit which will keep the 173 174 00:14:25,810 --> 00:14:31,090 aspect ratio of the original image while it's being resized. 174 175 00:14:31,090 --> 00:14:34,550 Now, at the moment, it's still a little bit too big. 175 176 00:14:34,570 --> 00:14:42,070 So I'm going to change its size by searching for the frame modifier, and then I'm going to drop it onto 176 177 00:14:42,070 --> 00:14:51,750 my image, and I want my image to be, maybe, have a width of 150 and a height of 150. 177 178 00:14:51,790 --> 00:14:57,720 So that way it should be large enough to see, but not large enough to see the imperfections. 178 179 00:14:58,120 --> 00:15:03,040 Now that I've created my image, I don't really like how it's a square. 179 180 00:15:03,280 --> 00:15:06,940 So how can I turn it into a circle? 180 181 00:15:06,940 --> 00:15:09,820 Well, there is a modifier. 181 182 00:15:09,910 --> 00:15:12,630 You've guessed, called a Clip Shape. 182 183 00:15:13,090 --> 00:15:18,940 And this allows us to clip the shape using a particular shape. 183 184 00:15:19,030 --> 00:15:26,440 And if you remember, if we go back to our components here, we've got loads of shapes down here: ellipse, 184 185 00:15:26,530 --> 00:15:30,740 circle, rectangle, rounded rectangle, a whole bunch of things. 185 186 00:15:30,760 --> 00:15:38,440 So let's see how we would do this. In order to clip our current image, 186 187 00:15:38,440 --> 00:15:46,800 we have to add this clip shape as a modifier to the image. And by default, it's set as a circle. 187 188 00:15:46,810 --> 00:15:55,030 Now, once it reloads, you can see my image has now turned into a circular profile photo. Pretty easy, right? 188 189 00:15:55,990 --> 00:15:56,260 Now, 189 190 00:15:56,290 --> 00:16:02,020 what if in addition to the circle, I wanted a little border around my profile image. 190 191 00:16:02,020 --> 00:16:03,550 What can I do to achieve that? 191 192 00:16:04,120 --> 00:16:12,890 Well, I could use something called Overlay and this layers a second view on top of the existing view. 192 193 00:16:12,940 --> 00:16:20,140 So that means our image is going to be behind and our overlay is going to go on top, and we get to put 193 194 00:16:20,140 --> 00:16:21,820 something in the overlay. 194 195 00:16:21,820 --> 00:16:24,750 In my case, it's just going to be drawing a circle. 195 196 00:16:24,760 --> 00:16:28,810 Let's go ahead and add our overlay to our image. 196 197 00:16:29,200 --> 00:16:36,490 And at the moment, the overlay is trying to overlay some text. But what I actually wanted to overlay is 197 198 00:16:36,580 --> 00:16:46,480 a circle object. And instead of just a normal circle which is going to obscure my face, I'm going to change 198 199 00:16:46,480 --> 00:16:56,140 the circle into a stroke. So that instead of being a filled shape, it becomes a line shape. And the content 199 200 00:16:56,170 --> 00:16:58,910 of the stroke is going to be a color, 200 201 00:16:58,930 --> 00:17:05,650 so I'm going to say Color.white, and the line width is going to be a floating-point number which I'll 201 202 00:17:05,650 --> 00:17:07,330 set to maybe 5. 202 203 00:17:07,960 --> 00:17:15,060 So, now you can see there's a picture of me inside a white border which is laid on top of my image. 203 204 00:17:15,100 --> 00:17:15,910 Pretty neat, right? 204 205 00:17:16,300 --> 00:17:18,770 And so far, so very easy. 205 206 00:17:20,330 --> 00:17:27,380 Now, the next thing I'm going to do is I want to add some contact details, so that when people have downloaded 206 207 00:17:27,380 --> 00:17:31,620 the app,. they can get in touch with me through email or through phone. 207 208 00:17:31,610 --> 00:17:38,990 So let's separate out this section which is kind of about me from the section which is going to be my 208 209 00:17:38,990 --> 00:17:47,700 contact details. And to do that, I'm going to use a divider component. So if you scroll down here, there's 209 210 00:17:47,700 --> 00:17:51,180 a whole bunch of shapes and there's this one called a divider. 210 211 00:17:51,180 --> 00:17:54,700 I'm going to add that right at the bottom of my VStack. 211 212 00:17:54,810 --> 00:18:02,340 And once it reloads, you'll be able to see it's now separated out my content into top and bottom areas. 212 213 00:18:02,430 --> 00:18:07,580 So below my divider, I'm going to create another shape. 213 214 00:18:07,860 --> 00:18:11,260 So I'm going to set this to you as a challenge. 214 215 00:18:11,280 --> 00:18:13,870 This is the effect that I'm going for. 215 216 00:18:13,920 --> 00:18:16,420 It's a rounded rectangle shape. 216 217 00:18:16,530 --> 00:18:21,780 And on top of the shape, I've got a overlaid text component. 217 218 00:18:21,870 --> 00:18:29,130 See if you can achieve this effect using what you've already learned. So, pause the video and compare against 218 219 00:18:29,130 --> 00:18:31,640 this template to complete the challenge. 219 220 00:18:35,180 --> 00:18:35,490 All right. 220 221 00:18:35,520 --> 00:18:40,710 So, I already gave you a clue that I'm going to use a rounded rectangle. 221 222 00:18:40,890 --> 00:18:45,380 So around a rectangle is simply a rectangle with a corner radius. 222 223 00:18:45,390 --> 00:18:52,290 So if we go ahead and drag that down, maybe just below the divider in our code, you can see that it creates 223 224 00:18:52,290 --> 00:18:59,800 this gigantic rounded rectangle which is trying to fill up all the available space in the VStack. 224 225 00:19:00,010 --> 00:19:04,260 The first thing we need to do is to make it a little bit smaller. 225 226 00:19:04,350 --> 00:19:11,580 So I'm going to add a modifier which, remember, is the frame modifier that changes the size. 226 227 00:19:11,760 --> 00:19:15,670 And I'm going to drag it down and put it in here. 227 228 00:19:15,960 --> 00:19:21,690 In this case, it's got a width and a height, but actually both of these properties are optional. 228 229 00:19:21,780 --> 00:19:27,730 So I can if I want to just let the width be set by the parent. 229 230 00:19:27,730 --> 00:19:35,190 So it's going to try and fill as much space as it has access to and only defined the height. 230 231 00:19:35,190 --> 00:19:38,610 So in my case, the height is roughly around 50. 231 232 00:19:38,610 --> 00:19:44,460 Don't worry if you've got 40 or 60 as long as it looks just about right, then it's fine. 232 233 00:19:44,460 --> 00:19:51,000 Now that I've got a frame, I can see that my rounded rectangle is a little bit less on the round and 233 234 00:19:51,000 --> 00:19:53,520 a little bit more on the rect side. 234 235 00:19:53,580 --> 00:20:01,170 So let's change the corner radius to a little bit higher. Instead of 20 people, we can make it 25. 235 236 00:20:01,230 --> 00:20:06,360 And this way it looks a lot more like the image that I showed you. 236 237 00:20:06,390 --> 00:20:11,330 So the next thing we have to do is change it to a white color. 237 238 00:20:11,580 --> 00:20:18,870 And the easiest way of doing this is to set the foreground color to white. 238 239 00:20:19,170 --> 00:20:26,760 And notice how with everything, text or shapes, you can always set the foreground color as long as it's 239 240 00:20:26,760 --> 00:20:28,430 something that is a vector image. 240 241 00:20:28,530 --> 00:20:37,510 So not something that is JPG or PNG, you can always set its foreground color. So I said that on top 241 242 00:20:37,510 --> 00:20:42,090 of this rounded rectangle, we were going to add an overlaid text. 242 243 00:20:42,430 --> 00:20:50,380 So let's go ahead and search for overlay and drag and drop this onto our rounded rectangle and we're going 243 244 00:20:50,380 --> 00:20:57,250 to add a text component. And our text component is going to be the phone number that we're going to show 244 245 00:20:57,250 --> 00:20:58,140 people. 245 246 00:20:58,150 --> 00:21:00,760 So let's add a phone number, 246 247 00:21:00,760 --> 00:21:03,480 123 456 789. 247 248 00:21:03,520 --> 00:21:04,030 That's it. 248 249 00:21:04,030 --> 00:21:04,390 Done. 249 250 00:21:04,390 --> 00:21:05,720 There's our phone number. 250 251 00:21:05,830 --> 00:21:07,930 But we can't see it. 251 252 00:21:07,960 --> 00:21:09,730 What's going on? 252 253 00:21:09,730 --> 00:21:13,150 Well, we have to change the color of the text. 253 254 00:21:13,150 --> 00:21:18,280 You can see that when I click on this text component it's actually getting highlighted in the preview. 254 255 00:21:18,850 --> 00:21:23,080 But at the moment, it's actually set to be the same as the foreground color. 255 256 00:21:23,140 --> 00:21:27,590 So it's white which is why we can't see it, white on white. 256 257 00:21:27,610 --> 00:21:35,380 Let's go ahead and change its color, so its foreground color to black, so that we can actually see it 257 258 00:21:35,470 --> 00:21:44,740 up here. And in fact, a much better way of setting shape colors rather than foreground color is to use 258 259 00:21:44,800 --> 00:21:47,210 something called fill. 259 260 00:21:47,680 --> 00:21:53,900 So we can fill our rounded rectangle with some content. 260 261 00:21:54,220 --> 00:21:58,810 And in my case, this content is simply just going to be a color. 261 262 00:21:59,320 --> 00:22:04,270 So we're filling that shape with a white color. 262 263 00:22:04,270 --> 00:22:11,380 And now you can see that even if our text didn't have a foreground color, it would be automatically set 263 264 00:22:11,530 --> 00:22:12,750 as black. 264 265 00:22:12,760 --> 00:22:14,270 So both ways work. 265 266 00:22:14,380 --> 00:22:17,670 This involves a little bit more reading from the documentation. 266 267 00:22:17,830 --> 00:22:24,790 But as long as you've managed to achieve this look, then consider yourself successful. 267 268 00:22:24,900 --> 00:22:32,310 So what if we wanted to add a little icon on the left here to signal that this is actually a phone number 268 269 00:22:32,400 --> 00:22:35,550 and not just my favorite number or something like that? 269 270 00:22:35,550 --> 00:22:42,480 Well in order to add that image of the phone icon, I'm going to use the SF Symbols that we talked about 270 271 00:22:42,510 --> 00:22:44,400 earlier on in the course. 271 272 00:22:44,400 --> 00:22:51,210 And if you remember, we downloaded the SF Symbols app which allows us to browse through all of the 272 273 00:22:51,210 --> 00:22:54,160 thousand or so images that we can choose from. 273 274 00:22:54,330 --> 00:22:57,780 And in my case, I'm going to search for an image of a phone 274 275 00:22:57,990 --> 00:22:59,660 and I'm going to choose the phone.fill 275 276 00:22:59,670 --> 00:23:09,000 to use in my app. Now, down here at the very end, I'm going to create an image. And instead of 276 277 00:23:09,000 --> 00:23:15,180 creating it like we have done up here where we've just given the name of the image as it appears in 277 278 00:23:15,180 --> 00:23:19,350 the Assets folder, I'm going to choose a different initializer. 278 279 00:23:19,350 --> 00:23:25,140 I'm going to choose the one that takes a system name. And that system name refers to the name that we 279 280 00:23:25,140 --> 00:23:28,890 saw over here from the SF Symbols. 280 281 00:23:28,890 --> 00:23:36,840 So I'm gonna put phone.fill. And once it updates, you can see that there's that little icon right 281 282 00:23:36,840 --> 00:23:40,130 there, the little phone icon. 282 283 00:23:40,230 --> 00:23:42,790 So here's a challenge for you. 283 284 00:23:43,020 --> 00:23:50,220 See if you can use that image that we created just now from the SF Symbols to add it into our little 284 285 00:23:50,220 --> 00:23:52,170 rounded rectangle here. 285 286 00:23:52,260 --> 00:23:59,100 The goal that you're looking to achieve is something like this with the phone image in green right next 286 287 00:23:59,100 --> 00:24:00,690 to our phone number, 287 288 00:24:00,810 --> 00:24:04,170 all nested inside this rounded rectangle. 288 289 00:24:04,170 --> 00:24:07,070 So pause the video and see if you can complete this challenge 289 290 00:24:12,210 --> 00:24:12,480 All right. 290 291 00:24:12,510 --> 00:24:14,340 So the first part is easy. 291 292 00:24:14,460 --> 00:24:21,330 If we wanted to change the color of our image, all we have to do is add a foreground color modifier to 292 293 00:24:21,330 --> 00:24:21,480 it, 293 294 00:24:25,660 --> 00:24:29,700 and I'm going to change it to green to match the background. 294 295 00:24:29,800 --> 00:24:37,240 Now, the next part is how do we get our image and our text to be horizontally aligned. 295 296 00:24:37,540 --> 00:24:40,330 Well, it sounds like the job for an HStack, 296 297 00:24:40,360 --> 00:24:40,640 right? 297 298 00:24:41,170 --> 00:24:50,160 So, in SwiftUI, we can't actually select multiple items yet and try to embed them both into a stack, 298 299 00:24:50,500 --> 00:24:52,540 instead you have to select one. 299 300 00:24:52,540 --> 00:24:55,930 So in this case, it's going to be the text in the overlay 300 301 00:24:55,930 --> 00:25:03,790 and I'm going to put it into an HStack, and then I can move my image to the front of the HStack. 301 302 00:25:03,820 --> 00:25:09,310 Remember that the HStacks go from left to right and the VStacks go from top to bottom. 302 303 00:25:09,610 --> 00:25:13,350 So if you want something right at the top, then keep it at the top of the stack. 303 304 00:25:13,410 --> 00:25:18,600 And if you want something right at the left, keep it at the top of the HStack. 304 305 00:25:18,640 --> 00:25:25,090 So, now I've got my phone and my phone number inside my rounded rectangle. 305 306 00:25:25,090 --> 00:25:31,840 The only thing to change is that maybe it would be nice to have a bit of padding so that my rounded 306 307 00:25:31,840 --> 00:25:35,650 rectangle is not all the way touching the edges. 307 308 00:25:35,650 --> 00:25:42,520 Now, in web development or web design, we would normally probably just add a margin to this rounded rectangle 308 309 00:25:43,090 --> 00:25:46,360 or we might add some padding to theHStack. 309 310 00:25:46,360 --> 00:25:53,830 But the way that we do it in US development is we actually add the padding to the component that needs 310 311 00:25:53,830 --> 00:25:55,180 to be padded away. 311 312 00:25:55,510 --> 00:26:00,370 So if you come from web design, then you'll think of it as the margin to add the padding. 312 313 00:26:00,370 --> 00:26:07,960 I'm going to find my padding in my modifiers, and then I'm just going to add it right at the end. 313 314 00:26:07,960 --> 00:26:15,700 And I'm going to add a padding to all four sides, top, left, right, and bottom. That's starting to look pretty 314 315 00:26:15,700 --> 00:26:16,390 nice. 315 316 00:26:16,720 --> 00:26:23,170 But if I wanted to create another one of these, I don't want to have to retype all of this code and have 316 317 00:26:23,230 --> 00:26:25,390 all of this repeated code. 317 318 00:26:25,390 --> 00:26:31,630 So how can I extract this rounded rectangle so that I can reuse it? 318 319 00:26:31,690 --> 00:26:39,040 Well, I can hold down my command key and select my rounded rectangle which contains pretty much all the 319 320 00:26:39,040 --> 00:26:40,920 components that are reusable. 320 321 00:26:41,140 --> 00:26:48,790 And then I'm going to click on extract subview. And you can see here's my extracted view that it's taken 321 322 00:26:48,880 --> 00:26:56,020 out of my code and you can see that Xcode is refracted it and is asking me the name for both of them. 322 323 00:26:56,110 --> 00:27:03,970 So I'm gonna call this the InfoView because it's gonna display my email and my telephone number. 323 324 00:27:04,030 --> 00:27:11,720 And to make this reusable, I have to change the icon that's going in it and the text that's going inside. 324 325 00:27:11,740 --> 00:27:18,130 Now, you might even want to have a custom color or a custom fill color for the rounded rectangle, the custom 325 326 00:27:18,130 --> 00:27:18,820 height. 326 327 00:27:18,820 --> 00:27:24,910 But in my case, I'm going to keep it simple. I want my InfoViews to pretty much all look the same, but 327 328 00:27:24,910 --> 00:27:27,310 I do want to change the text that goes in. 328 329 00:27:27,310 --> 00:27:37,560 So this is going to be a string, and also the image name. So this is also going to be a string. 329 330 00:27:37,590 --> 00:27:47,470 And then I'm going to replace this systemName with imageName and I'm going to replace the text with the text 330 331 00:27:47,530 --> 00:27:49,390 property right here. 331 332 00:27:49,420 --> 00:28:00,550 So, now I can initialize a new image view just below the divider and add in some values for those two 332 333 00:28:00,550 --> 00:28:01,510 inputs. 333 334 00:28:01,510 --> 00:28:08,500 So the text is going to be my phone number and the image view is again going to be phone.fill. 334 335 00:28:08,650 --> 00:28:14,860 So, now once it updates it should look exactly the same as before because I haven't changed anything 335 336 00:28:15,310 --> 00:28:23,420 other than refactor out this InfoView which I can now reuse in a lot of places. In order to keep our 336 337 00:28:23,420 --> 00:28:31,910 code neat, often you'll find that we would create a new file which will create as a new SwiftUI View, 337 338 00:28:32,900 --> 00:28:39,190 and we'll call this view the InfoView. And inside this InfoView, 338 339 00:28:39,200 --> 00:28:48,110 I'm going to delete the default struct that gets created. And instead, I'm going to cut and paste in this 339 340 00:28:48,200 --> 00:28:51,170 InfoView that I created just now. 340 341 00:28:51,200 --> 00:29:01,400 So, now when you actually take a look at it in terms of the preview, you can pass in some parameters for 341 342 00:29:01,400 --> 00:29:02,450 its initializer. 342 343 00:29:02,480 --> 00:29:05,970 So text and imageName. So let's initialize 343 344 00:29:05,990 --> 00:29:08,660 here our text and imageName. 344 345 00:29:08,660 --> 00:29:10,920 Text, I'm just gonna put "Hello" and the imageName, 345 346 00:29:10,940 --> 00:29:18,200 phone.fill again. And this data is just used to create the preview here. 346 347 00:29:18,620 --> 00:29:28,000 So let's click Try Again and let it try to render this InfoView. You can see that we can now just see 347 348 00:29:28,000 --> 00:29:37,340 the InfoView. And because this is just a single component, it doesn't really make sense to preview it 348 349 00:29:37,460 --> 00:29:39,020 in an entire phone, 349 350 00:29:39,020 --> 00:29:39,310 right? 350 351 00:29:39,320 --> 00:29:49,010 It looks a bit lonely there. So we can instead use a modifier on the preview by calling previewLayout 351 352 00:29:49,430 --> 00:29:54,620 and the value to pass in is sizeThatFits. 352 353 00:29:54,620 --> 00:30:00,260 So this is going to render our preview to fit the size of our component. 353 354 00:30:00,290 --> 00:30:09,120 So, now we can actually see it in all its glory and instead of being rendered inside a phone bezel. 354 355 00:30:09,520 --> 00:30:16,780 So, now that we've separated out our InfoView, we can go back to our ContentView and create our second 355 356 00:30:16,780 --> 00:30:17,500 InfoView. 356 357 00:30:17,920 --> 00:30:25,120 So right below the phone number one, I'm gonna create another one which is going to hold my email. 357 358 00:30:26,110 --> 00:30:33,910 So the text in this case is going to be my email, angela@email.com. And my image name for this 358 359 00:30:34,000 --> 00:30:37,360 email one is going to come from SF Symbols. 359 360 00:30:37,360 --> 00:30:40,590 So let's search for mail and see what we get. 360 361 00:30:40,720 --> 00:30:48,110 This envelope.fill looks pretty good, so let's use that. So envelope.fill. Cool. 361 362 00:30:48,580 --> 00:30:50,400 So there it is. 362 363 00:30:50,530 --> 00:30:58,630 We've now managed to develop a fully designed business card app using all sorts of advanced layout modifiers, 363 364 00:30:59,080 --> 00:31:06,970 as well as seeing how we can extract views for repeated use and to preview the components in their own 364 365 00:31:07,180 --> 00:31:09,130 unique sizes. 365 366 00:31:09,140 --> 00:31:15,940 So I hope you had fun with this project. And in the next module, I'm going to show you how to build a 366 367 00:31:15,940 --> 00:31:21,260 app that actually has functionality in addition to appearance. 367 368 00:31:21,370 --> 00:31:24,040 So for all of that and more, I'll see you there.