Your first SwiftUI screen
Tags: ios, swift, swiftui
Published: 2020-02-11 07:51:44

---
title: Your first SwiftUI screen
published: true
description: 
tags: ios, swift, swiftui
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/i9pyfyb9u18tudozseyv.png
series: CometChat SwiftUI course
canonical_url: https://www.cometchat.com/tutorials/your-first-swiftui-screen-2-7/
---

SwiftUI is a unifying framework in more ways than one. Whether you're building an Apple Watch, Apple TV, iPhone, iPad or even Mac apps, SwiftUI will let you do that. Whether you're a designer, web developer or simply someone interested in building apps, SwiftUI is still for you. It might take a bit longer than for seasoned iOS veterans, but you'll get the hang of things!

Once you're on the other side of this course, you won't just be an iOS developer  **you'll be a SwiftUI developer**. Capable of building for all Apple platforms!

This course will guide you through building a real-world chat application. You'll build each part of the app including logging the user in, displaying their contacts and chatting over the internet. By building a real app, you'll quickly learn practical SwiftUI skills that you can use in the real world.

In this first part, you'll make a welcome screen for the app. You'll learn about existing SwiftUI views, how to make your own views, how to lay them out and space them as well as how to style them to your liking.

On your way to victory, SwiftUI might try to sabotage you at some point with its opaque error messages or hard-to-find APIs. Remember, fortune favors the brave, so let's dive in with courage!

> You can find the finished project of this part of the SwiftUI course [here](https://github.com/cometchat-pro-tutorials/swift-ui-chat).

## Making SwiftUI Views

We'll start our SwiftUI adventure by building out a welcome screen for our app. It will be a static screen with some information, an image and buttons to either log in or sign up to our chat service.

[Your first SwiftUI screen!](https://thepracticaldev.s3.amazonaws.com/i/izoybo8y7r0zl1j2ylco.png)

A SwiftUI app is a huge tree of `View`s. `View` is a SwiftUI protocol that represents any view that can be shown on the screen, whether it's a huge detail screen or a simple label.

![SwiftUI View hierarchy](https://paper-attachments.dropbox.com/s_B4BD5BC1113396FE6C7C810B61229600F0589EE048E774B079748EDF04FD858D_1572001105818_Screenshot+2019-10-25+at+12.52.28.png)

Let's start by creating a new SwiftUI app. Open up **Xcode**. For this to work, you'll need Xcode 11 or later.

> I am creating this course in collaboration with CometChat, a modern chat platform to help you add chat to you Swift app. During the next few weeks, we’ll be releasing installments of our free SwiftUI course here on dev.to! In the course, you’ll dive deep into SwiftUI by building a real-world production-scale chat app, learning SwiftUI in a practical way, on a scale larger than a simple example app. Follow me to get notified of future parts of this course! You can also follow [@CometChat](https://twitter.com/cometchat) on Twitter see the course of [CometChat’s blog](https://www.cometchat.com/blog/).

[![](https://thepracticaldev.s3.amazonaws.com/i/avpunu4hqp1ut7enf5tq.png)](https://www.cometchat.com)

On the Xcode welcome screen, click **Create a new Xcode project**. Select the **Single View App** template under **iOS** and hit **Next**. Name the app anything you'd like. I named my app "CometChat". Make sure **SwiftUI** is selected as the **User Interface** and click **Next** again. Select a good location to save the project and click **Create**.

![Creating a new SwiftUI app in Xcode](https://thepracticaldev.s3.amazonaws.com/i/644wvha36zyq2dfpeeoo.png)

Congrats! You just made your first SwiftUI app. This is the end of this course. *Just kidding*.

Next, you'll create a new SwiftUI view. Click **File > New > File...** and, as the template, select **SwiftUI View** and name it **WelcomeView**.

You'll get presented with an almost empty struct, except for one computed property called `body`. **This is the most important part of a view.** `body` returns the contents of your view. iOS will periodically call this computed property to re-draw what's on the screen.

You might have noticed `body`'s type is `some View`. `View` is a protocol, and the `some` keyword tells Swift that `body` can be any concrete type, as long as it conforms to `View`.

Change the contents of the struct to the following:

```swift
struct WelcomeView: View {

  var body: some View {
    Text("Create an account")
  }

}
```

On the right of your code, you'll see the **Canvas**. This is where you can preview the views you're making. If the preview updating is paused, click the **Resume** button in the top-right corner.

![Your first SwiftUI view!](https://thepracticaldev.s3.amazonaws.com/i/4v5y21tjf3je028o588q.png)

As you make changes to your code, the Canvas will update to show your changes. At least in theory. Often the canvas will be too quick to update and try to compile partially-written code or run into some other issue. You'll get used to clicking **Try Again** and **Resume** a lot. :)

### Arranging SwiftUI views with stacks

Let's add another label to the view, below the one you just added. You might be tempted to simply add another `Text` below the current one, but if you do that you'd get a compiler error. The error happens because `body` is a single `View`: You can't return two values. Instead, you need a view that would wrap *around* the two texts, like a SwiftUI birthday present.

SwiftUI has a couple of different views that group other views and the one you'll use the most is `VStack` and `HStack`. These are the SwiftUI equivalents to UIKit's UIStackView, stacking for **v**ertical and **h**orizontal stack views, respectively. If you're coming from web development, `VStack` and `HStack` are the Flexbox of SwiftUI.

These two views are your **primary layout tool** in SwiftUI. By arranging items into stacks, nesting stacks within stacks and controlling stack alignment and item spacing you can make almost any layout imaginable.

Let's change `body` so that it returns a vertical stack of two text views:

```swift
var body: some View {
  VStack {
    Text("Create an account")
    Text("Connect with people around the world")
  }
}
```

You'll see the two labels centered in the middle of the preview screen. 

![A SwiftUI VStack](https://thepracticaldev.s3.amazonaws.com/i/i1wn4adl9d7acj725o7q.png)

If you look at the screen we're trying to make, though, the two texts need to be aligned to the left and sit on top of the view. You can align items in a stack by passing the alignment in the stack's initializer:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
    Text("Connect with people around the world")
  }
}
```

Now the texts are aligned to the left, but they're still not on the top of the screen. 

![Left-align items in a SwiftUI VStack](https://thepracticaldev.s3.amazonaws.com/i/54jhb1c8ajs3mzao16jp.png)

Let's look at how we can fix that.

#### Vertically aligning VStack items with spacers

The stack's `alignment` controls the alignment of the items along the _opposite axis of the stack_, so for `VStack`, it controls the horizontal alignment. To align items along the _major axis_ you can either manually space the items or use a special view called `Spacer`.

A `Spacer`, as its name suggests, is an empty view that stretches out to fill out as much space as it can. When you place it inside a `VStack`, it will stretch _horizontally_. If you place it in an `HStack`, it stretches *vertically*.

Add a spacer to the bottom of your stack to see what happens:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
    Text("Connect with people around the world")
    Spacer()
  }
}
```

If `VStack` is the birthday present, the spacers are the birthday party balloons, filling up the horizontal space as long as they can, pushing the two text views to the top of the screen.

To get the feel for how spacers behave, experiment by placing spacers at different positions inside the stack. Here are a couple of examples:

![SwiftUI VStack and Spacer cheat sheet](https://thepracticaldev.s3.amazonaws.com/i/y4ajo4ate7855obyxtcd.png)

As you can see, by placing spacers at different positions you can align and space out your items anywhere in the stack. To fine-tune the spacing, you'll use _padding_ — but you'll read more on that later in this part of the SwiftUI course.

For now, we'll take a break from laying out our view and venture into styling the text.

### Styling SwiftUI views with `View` methods

`View`s have all kinds of methods to tweak their properties, whether its changing their size, colors, state, opacity or anything else that can be changed. Some of these methods are common to all views, like methods for changing the frame or padding. Others are specific to that view, such as the font of a `Text` or the enabled state of a `Button`.

According to the screenshot of the view we're building, the second text in our stack needs to have a big and bold font. To make this change, call the `font` method on the text:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")

    Text("Connect with people around the world")
      .font(Font.largeTitle.weight(.bold))

    Spacer()
  }
}
```

If you're used to UIKit, you're probably familiar with classes like `UIFont` or `UIColor`. SwiftUI has its equivalents, but drops the `UI` prefix and makes them a struct. 

There's also one big difference between the UIKit and SwiftUI versions: **SwiftUI's fonts and colors are _late binding_.** This means that a `Font` is just a _token_ or an identifier for some font. This token only gets resolved to a specific font during runtime, depending on the environment it's running in. For instance, `Font.largeTitle` gets resolved to San Francisco on iOS, but could be Helvetica [on the web](https://github.com/SwiftWebUI/SwiftWebUI).

SwiftUI modifier methods are _non-mutating_. Instead, they return a new `View` with the changes applied. This has two consequences. First, you can chain modifier calls one after the other.

```swift
Image("welcome")
  .resizable() // returns a new Image
  .aspectRatio(contentMode: .fit) // returns a new View
  .padding(.bottom, 35) // returns a new View
```

Secondly, because each of these methods creates a new view, the order of calling the methods can sometimes be important. A modifier called later can override what you set earlier, like in CSS or when subclassing a Swift class.

If you're the kind of developer who prefers a GUI over plain code, you can **Control-Option-Click** a SwiftUI view (either in the code or the preview) and open the **SwiftUI Inspector**.

![SwiftUI Inspector in Xcode](https://thepracticaldev.s3.amazonaws.com/i/jkv56ua2hmxgbz1djqs9.png)

This opens up a popup window that will let you tweak the settings of a view. As you make changes, SwiftUI will generate code for those changes and add them to your `body`.

### Changing the color of a SwiftUI Text

While we're beautifying our views, why not add some color. As you can guess by now, adding color is a simple matter of calling a method on the label:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")

    Text("Connect with people around the world")
      .font(Font.largeTitle.weight(.bold))
      .foregroundColor(.accentColor)

    Spacer()
  }
}
```

Just like `Font`, `Color` is also a late-binding token, which means that the actual color value of the color above will depend on the current environment, including what platform it's running on as well as whether it's running in light or dark mode.

Even SwiftUI `Color`s with specific names like `.blue` will result in a different color in light and dark mode. These are called _adaptive colors_, and you can make your own!

### Adding your own adaptive colors

You'll add a new color for the text content of your app. Open **Assets.xcassets** in the main folder of your app in Xcode. Right-click on the list of assets and select **New Color Set**. At first, you'll see a white color with "Universal" below it. But, if you take a look at the **Attributes Inspector**, you'll see there's a bunch of different environment combinations you can set.

![Adding a SwiftUI adaptable color for dark mode](https://thepracticaldev.s3.amazonaws.com/i/qt7xpt2zs9cdam5fqos1.png)

For instance, you can set one color for CarPlay in dark mode, a different color for Apple TVs in dark mode, and a third color for iPhones.

For now, select only **Universal** in the **Devices** list, and **Any, Dark** in the **Appearances** dropdown. This allows you to set a different color for light and dark mode on all devices.

Select the **Any Appearance** color and in the **Attributes Inspector** select **8-bit Hexadecimal** for the **Input Method** and enter the hex value #`2D313F`. 

![Adding a SwiftUI adaptable color for dark mode](https://thepracticaldev.s3.amazonaws.com/i/z8eft8r7agwbgid5cblg.png)

For Dark Appearance plain white will suffice. Select the **Color** in the sidebar and rename it to **body**. This name is important because that's how we'll access it in code.

Create a new plain Swift file called **Colors.swift**. Replace the contents of the file with the following:

```swift
import UIKit
import SwiftUI

extension Color {
  static let body = Color("body")

  static let cometChatBlue = Color(red: 27 / 255, green: 71 / 255, blue: 219 / 255)
  static let shadow = Color(red: 27 / 255, green: 71 / 255, blue: 219 / 255, opacity: 0.3)
  static let background = Color(red: 248 / 255, green: 249 / 255, blue: 251 / 255)
}

extension UIColor {
  static let body = UIColor(red: 45 / 255, green: 49 / 255, blue: 63 / 255, alpha: 1)
}
```

This adds new static properties to `Color` and `UIColor`. We can use these colors throughout our app without having to copy and paste color names or specific values. Having everything in one place also means we can easily change these colors later.

Now that you have the color you can use it to make your text prettier. Head back to **WelcomeView.swift** and add a color to the first text:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
      .foregroundColor(.body)

    Text("Connect with people around the world")
      .font(Font.largeTitle.weight(.bold))
      .foregroundColor(.cometChatBlue)

    Spacer()
  }
}
```

![Adding a SwiftUI adaptable color for dark mode](https://thepracticaldev.s3.amazonaws.com/i/8beaz6oapubbe082t2y5.png)

Extending `Color` with static properties is a great way to add reusability to our app. You can go a step further to make _any changes_ to a view reusable. Let's do that next.

### Styling SwiftUI views with view modifiers

So far you have a title and a body text styled as they look in the screenshot above. You'll use the same text treatment (font and color combination) throughout your whole app. Instead of copying and pasting all the method calls in every `View` with texts, it would be better to have a way to mark titles and body text in a more reusable way.

SwiftUI lets you do that with **View Modifiers**. Structs and classes in your app can implement the `ViewModifier` protocol which has one required method that receives and returns a view. The idea is that you receive a view, perform any necessary transformations and return it back to the caller.

You'll add two modifiers, one for the body text and one for titles. Create another plain Swift file and name it **TextModifiers.swift**. Add a new view modifier to the file:

```swift
import SwiftUI

struct TitleText: ViewModifier {
  func body(content: Content) -> some View {
    content
      .font(Font.largeTitle.weight(.bold))
      .foregroundColor(.cometChatBlue)
  }
}
```

You implement the required method by receiving a view, applying a new font and foreground color and returning the changed view.

Similarly, add another struct below the one you just created for the body text:

```swift
struct BodyText: ViewModifier {
  func body(content: Content) -> some View {
    content
      .foregroundColor(.body)
  }
}
```

For the body text, you'll leave the font as it is and only change the color. Now, you can go back to **WelcomeView.swift** and replace the styling you applied with the modifiers by calling the `modifier` method on the text views:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
      .modifier(BodyText())

    Text("Connect with people around the world")
      .modifier(TitleText())

    Spacer()
  }
}
```

You can now use these modifiers in any future views. When you want to change the look of your apps content, you can change the modifier the apply the changes everywhere in your app.

Since view modifiers return a `View`, you have the complete power of SwiftUI inside a modifier. This means you can even do complex changes like embed the view in a stack, scale it, adjust its spacing, add overlays and [make whichever changes you can think of](https://sarunw.com/posts/swiftui-viewmodifier/). 

### Spacing SwiftUI views with padding

I think that's enough styling for now. It's time to get back to laying out our screen with **padding**. SwiftUI doesn't have Auto Layout or constraints, but that doesn't mean you can't do everything you did in UIKit. It might be even easier. _At least sometimes._

The method you use for this is called `padding`, and it has two optional parameters:

```swift
func padding(
  _ edges: Edge.Set = .all, 
  _ length: CGFloat? = nil) 
  -> some View
```

The first parameter is the set of edges to apply the padding to, while the second is the actual value of the padding. By default, the first parameter applies the padding to all edges. If you omit the length, it will be `nil` which will apply the **default system padding** to the view.

Usually, you'd want to apply the default padding. The advantage of the default padding is that it's automatically adjusted to the device you're using. Smaller devices will have a smaller padding and vice-versa.

Change the `body` of your view to add a padding to both of the texts:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
      .modifier(BodyText())
      .padding()

    Text("Connect with people around the world")
      .modifier(TitleText())
      .padding([.bottom, .leading, .trailing])

    Spacer()
  }
}
```

To the body text, you add a default padding to every edge by calling `padding()`. The title text doesn't need a padding on top, so you add the system padding only to the bottom, leading (left) and trailing (right) edges.

[Adding padding to a SwiftUI view](https://thepracticaldev.s3.amazonaws.com/i/xcn3k2juk4vbr4jqm41u.png)

You can combine the first and second parameter of `padding` to achieve your desired effect. Here are some examples of different ways you can call `padding`:

- `padding()` applies system padding to all edges.
- `padding(.leading)` applies the system padding to the left edge.
- `padding([.bottom, .leading, .trailing])` applies the system padding to three edges.
- `padding(.top, 20)` adds a padding of 20 points to the top edge.
- `padding([.bottom, .top], 0)` makes the top and bottom padding zero.

By combining stacks and padding you can intuitively make pixel-perfect layouts. At least, once you get used to it. :)

### Nesting SwiftUI stacks

In UIKit, one of the most common view types are stack and table views. The same goes for SwiftUI: Your views will often be a big tree of nested stacks. In the screenshot of the screen you're making there's an image with a text below the two texts you just created. 

Both the image and the text are centered, so add another `VStack` inside the existing one, that you'll center horizontally:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
      .modifier(BodyText())
      .padding()

    Text("Connect with people around the world")
      .modifier(TitleText())
      .padding([.bottom, .leading, .trailing])

    VStack(alignment: .center) {
      Text("""
        This is a sample app.
        Create an account or login to begin chatting.
        """)
        .modifier(BodyText())
        .multilineTextAlignment(.center)
        .padding([.leading, .trailing], 40)
    }

    Spacer()
  }
}
```

You add another `VStack` that will hold the image and the text. The text also has the body text modifier. You make sure the text is centered and add a padding of 40 points on the leading and trailing edges, so it doesn't touch the edges of the screen.

![SwiftUI Nested VStacks](https://thepracticaldev.s3.amazonaws.com/i/v02ozcx5aarm4wsncg13.png)

### Displaying images in SwiftUI

Now that we added the text that's below the image, it's time to add the image. Image views in SwiftUI are called `Image`, and they can be tricky to parse at first.

Before you add an image view, you first need to add the image itself. You can find the [welcome image here](https://github.com/cometchat-pro-tutorials/swift-ui-chat/raw/master/CometChat/CometChat/Assets.xcassets/welcome.imageset/welcome.png).

Open **Assets.xcassets** and drag the image into the list of assets. Make sure the name is **welcome**.

Now, you can add a new `Image` to the inner `VStack`:

```swift
VStack(alignment: .center) {
  Image("welcome")
    .padding(.bottom, 35)
    .padding([.leading, .trailing], 80)

  Text("""
    This is a sample app.
    Create an account or login to begin chatting.
    """)
    .modifier(BodyText())
    .multilineTextAlignment(.center)
    .padding([.leading, .trailing], 40)
}
```

You give the `Image` the name of the asset you created. Give it a padding of 35 points at the bottom (between the image and the text), as well as a padding of 80 on the sides.

The image looks good, but there's a _small_ issue: Our whole UI is now broken.

![Making an Image resizable in SwiftUI](https://thepracticaldev.s3.amazonaws.com/i/rp26y2k9ltwkem5z93sl.png)

It would be ideal if the image scaled according to the device size and how much space it has to grow. On an iPhone SE, the image should be smaller than on an 11 Pro Max.

We'll deal with this issue in a second, but let's first take a look at how we can spot issues like this in the future.

### Previewing SwiftUI views on a different device

You can tweak the SwiftUI preview to see your views at different sizes. The preview screen isn't magic: It's loaded from a struct in the file that implements `PreviewProvider`. The preview provider is similar to a `View`. It has one computed property where you return what should be drawn inside the Canvas.

```swift
struct WelcomeView_Previews: PreviewProvider {
  static var previews: some View {
    WelcomeView()
  }
}
```

You can change this view in the same way you can change any other `View`. There are also preview-specific methods that control the size and look of the previews.

Call `previewDevice` inside the `previews` property and display an iPhone SE:

```swift
struct WelcomeView_Previews: PreviewProvider {
  static var previews: some View {
    WelcomeView()
      .previewDevice(PreviewDevice(rawValue: "iPhone SE"))
  }
}
```

![Making an Image resizable in SwiftUI](https://thepracticaldev.s3.amazonaws.com/i/2hma5xgpcn60364iod13.png)

You can now see that the image doesn't scale according to screen size. Let's fix that.

### Scaling a SwiftUI Image

To make an `Image` view resizable you need to, you guessed it, call the `resizable` method! Add the following two new lines to `body`:

```swift
VStack(alignment: .center) {
  Image("welcome")
    .resizable()
    .aspectRatio(contentMode: .fit)
    .padding(.bottom, 35)
    .padding([.leading, .trailing], 80)

  Text("""
    This is a sample app.
    Create an account or login to begin chatting.
    """)
    .modifier(BodyText())
    .multilineTextAlignment(.center)
    .padding([.leading, .trailing], 40)
}
```

By default the image will just scale to fill its available space, which you probably don't want. Usually, you want to maintain the image's aspect ratio so that it doesn't look stretched out. 

To do that in SwiftUI, you can use the `aspectRatio` method which receives a parameter telling it how to scale the image. `.fit` scales the image so that it always fits inside its space, leading to letter-boxing. On the other hand, `.fill` scales it so that it fills the whole space, but you won't see the whole image.

In the above code, you first call `resizable` on the image to tell SwiftUI that it can stretch out the image if needed. Then, you call `aspectRatio` with `.fit` to make sure the image always fits within the screen, 80 points from each edge.

![Making an Image resizable in SwiftUI](https://thepracticaldev.s3.amazonaws.com/i/s4djrbnde22aqkrtqsiq.png)

If you change the device back to `iPhone 11` in the preview you'll notice the image now scales to fit its available size, no Auto Layout needed.

We're almost done with our welcome screen! The final step is to add the two buttons on the bottom.

## Creating buttons in SwiftUI

To build out a screen like this in UIKit, you'd use a view controller, and house all of your view related things in there. Usually, this is _not_ how you'll build SwiftUI views.

SwiftUI does away with the distinction between view and view controller and it's built so that you compose tons of tiny views to build your screen.

That's what you've been doing: `Text`, `VStack` and `Image` are all small views that do one thing well, but by combining them you've created an already good-looking screen.

Now it's time we make your own small SwiftUI views that you can use throughout the app. These views will be the two buttons you see on the bottom of the screen you're building.

![Creating a Button in SwiftUI](https://thepracticaldev.s3.amazonaws.com/i/hvdxesp2d38yhseoxapm.png)

Create a new SwiftUI `View` file called **ButtonViews**, and change the struct to the following:

```swift
import SwiftUI

struct PrimaryButton: View {

  let title: String

  var body: some View {
    Text(title.uppercased())
  }
}
```

You need to build a big blue button with rounded corners. You'll start with a good old text view.

A button can hold _any other view_, no matter how complex. With that in mind, our button is looking a little plain.

At this point, you'll get an error because the automatically generated preview references the wrong view name. Change the preview to show your button:

```swift
struct ButtonViews_Previews: PreviewProvider {
  static var previews: some View {
    PrimaryButton(title: "Primary")
  }
}
```

![Creating a SwiftUI Button](https://dev-to-uploads.s3.amazonaws.com/i/yz5neq14kmyyrsd9ujl9.png)

We'll make it look better, but before we go on, let's do some preview setup to make our lives easier.

### Changing the size of a SwiftUI preview

Earlier in this section of the course, you learned how to preview your SwiftUI views on different devices. Most of your views will be reusable UI components, so it doesn't make sense to show a whole iPhone with a tiny view in the middle of a blank screen.

Instead, you can preview them in a small window. Change the preview struct to the following:

```swift
struct ButtonViews_Previews: PreviewProvider {
  static var previews: some View {
    PrimaryButton(title: "Primary")
      .previewLayout(.fixed(width: 300, height: 100))
  }
}
```

Now the preview shows a small rectangle that houses our button.

![Changing the preview size in SwiftUI](https://dev-to-uploads.s3.amazonaws.com/i/bojw21g5rsjh0ultmcey.png)

Nice and neat! Let's get back to our buttons.

### Styling SwiftUI buttons

Let's deal with that plain-looking button! Start by adding a background and a shadow to the button:

```swift
var body: some View {
  Text(title.uppercased())
    .background(Color.accentColor)
    .cornerRadius(5)
    .shadow(color: .shadow, radius: 15, x: 0, y: 5)
}
```

Okay, you now have a rounded blue blob, which is a start.

![Making a Button in SwiftUI](https://dev-to-uploads.s3.amazonaws.com/i/ymgp3gh0fhrmt23mbca9.png)

Next, change the color and add some padding around the text:

```swift
var body: some View {
  Text(title.uppercased())
    .fontWeight(.bold)
    .foregroundColor(.white)
    .padding()
    .frame(maxWidth: .infinity)
    .background(Color.accentColor)
    .cornerRadius(5)
    .shadow(color: .shadow, radius: 15, x: 0, y: 5)
}
```

There's one new method here: `frame`. While padding determines how much space there is around the content, the frame determines how big the content is.

You can either specify a constant size or you can make _suggestions_ to SwiftUI about how it should size the view. Here, you set the maximum width to infinite, making the view stretch to fit the size of its parent.

![Making a Button in SwiftUI](https://thepracticaldev.s3.amazonaws.com/i/nvegusjew8ksx7bxp6e1.png)

Our button is looking perfect! Let's add another, secondary button.

### Creating the secondary button

To create the secondary button, you'll use a complex programming technique used by generations of programmers: copying and pasting. Because SwiftUI views are short pieces of code that are all in a single struct, you can easily copy and paste a view, modify it slightly and get a whole new look.

For the secondary button, copy over the primary button and change the colors a bit to match the screenshot:

```swift
struct SecondaryButton: View {
  
  let title: String
  
  var body: some View {
    Text(title.uppercased())
      .fontWeight(.bold)
      .foregroundColor(.accentColor)
      .padding()
      .frame(maxWidth: .infinity)
      .background(Color.white)
      .cornerRadius(5)
      .shadow(color: .shadow, radius: 15, x: 0, y: 5)
  }
}
```

It looks great... _I think_. To see the button you need to change your preview first.

### Showing multiple SwiftUI previews

You might be tempted to replace `Primary` with `Secondary` in the preview and call it a day. But, why show just one view, when you can show both of them at once?

If you wrap the views inside a `Group`, the Canvas will show each grouped view as a separate preview.

```swift
static var previews: some View {
  Group {
    PrimaryButton(title: "Primary")
      .previewLayout(.fixed(width: 300, height: 100))
      
    SecondaryButton(title: "Secondary")
      .previewLayout(.fixed(width: 300, height: 100))
  }
}
```

Now you can see both of the buttons at once.

![Previewing two SwiftUI views at once](https://thepracticaldev.s3.amazonaws.com/i/4agglx3amdlh5quvn1dk.png)

This is especially useful when you have views that can show multiple states. For instance, we can show a preview for buttons that have long titles:

```swift
static var previews: some View {
  Group {
    PrimaryButton(title: "Primary")
      .previewLayout(.fixed(width: 300, height: 100))
    
    PrimaryButton(title: "This button has a really long title")
      .previewLayout(.fixed(width: 300, height: 100))
    
    SecondaryButton(title: "Secondary")
      .previewLayout(.fixed(width: 300, height: 100))
  }
}
```

![Showing multiple View states in a SwiftUI preview](https://thepracticaldev.s3.amazonaws.com/i/1meryrtk6jn4q21bvaog.png)

This makes it easy to see how your changes affect different states of your views, making sure you spot a lot of bugs without having to build and click around your app.

## Using custom SwitUI views

With our buttons created, let's add them to the welcome screen. Back in **WelcomeView.swift**, add a new `VStack` with the two buttons, the final addition to the welcome screen:

```swift
var body: some View {
  VStack(alignment: .leading) {
    Text("Create an account")
      .modifier(BodyText())
      .padding()

    Text("Connect with people around the world")
      .modifier(TitleText())
      .padding([.bottom, .leading, .trailing])

    VStack(alignment: .center) { ... }

    // New code:
    VStack(spacing: 30) {
      Button(action: { }) {
        PrimaryButton(title: "Log In")
      }
      
      Button(action: { }) {
        SecondaryButton(title: "Sign Up")
      }
    }
    .padding([.leading, .bottom, .trailing])
    .padding(.top, 40)
    // ---

    Spacer()
  }
}
```
You can use your `View`s just like any other SwiftUI view. After all, they're nothing more than a Swift struct conforming to a protocol. In the above code, you placed your views inside a `VStack`, and each inside a `Button`.

As opposed to UIKit's `UIButton`, `Button` is a completely blank view. All it does is make its contents touchable and manages button state changes. How the button looks is completely up to you. In the code above, you used `PrimaryButton` and `SecondaryButton` to display a button label. Instead of that, you could have used `Text`, `Image` or any other SwiftUI view.

Currently, the buttons don't do anything. But, if you run the project and tap on the buttons, you'll notice they light up as you tap them. That animation is coming from `Button`.

Earlier in this part of the course you used padding to space out views within a stack. If you want the space between each of the items to be the same, you can pass the `spacing` parameter to a stack's initializer. The stack will then take care of the spacing for you. You can even use padding a spacing in tandem for those pixel-perfect designers among you!

![Your first SwiftUI screen!](https://thepracticaldev.s3.amazonaws.com/i/izoybo8y7r0zl1j2ylco.png)

And with that, your welcome screen is done!  This now looks exactly like the original screenshot, giving the user some information about the app and a way to log in and register. Right now, these buttons don't do anything. In the next part of this SwiftUI course, you'll navigate to a login and registration screen!

## Conclusion

In the span of one part of this course, you went from having no app and no SwiftUI knowledge to building out your first full SwiftUI screen! With this knowledge and some googling, you now have the skills to build almost any static SwiftUI screen.

You know about views, how to create them, lay them out and space them around. You also learned about adding and customizing text, creating buttons and displaying images.

SwiftUI shows its power here: By learning a small number of tools you can build out any UI you can imagine. That's elegant, flexible design.

Your layout knowledge doesn't need to end here, though. For the A-grade students among you, check out the WWDC session called "[Building Custom Views with SwiftUI](https://developer.apple.com/videos/play/wwdc2019/237/)" which goes more in-depth into how the layout system works and some other tricks you can use.

There's still much to learn! You now know how to make static UIs, but in the next part, you'll learn how to navigate to a login screen and manage the state for your UIs. Keep reading to build out the login screen of your app!