Prototype a Custom Toggle in SwiftUI

Part 1: Layout basics with stacks, shapes and modifiers

In this tutorial we’re going to prototype a simple toggle with SwiftUI that animates other elements in our view. In part one we’ll learn how to:

  • use stacks to arrange elements on-screen.
  • build a toggle using built-in shapes and modifiers.
  • add colors, text styles and images to match designs.

In part two we’ll add tap gestures and animations to make it interactive.

First things first, let’s take a look at what we’re building. Head over to this Figma file to look at the designs.

Screenshot of sample design in Figma

Now that we know what we’re building open Xcode and create a new project. Select App from the menu and name the project CustomToggle. Make sure SwiftUI is selected in the interface dropdown below. In the ContentView file you’ll see a TextView with “Hello World”. Press command+option+p to see a live preview of our code— the 1st time running live preview is usually slow.

Default Xcode project with Hello World.

Try changing the text to “Customize” like in our design — the live preview should update as you type. Right below add another Text view for our sub-header. You’ll notice when you add the second text view the preview looks off. That’s because we haven’t told Swift about how we want our layout to work. To fix this we’re going to use stacks. Stacks are what you use to arrange views horizontally, vertically, above and below each other. In this case we want the two Text views to be stacked vertically. To do this simply wrap the Text views in a VStack{} like this:

Next, let’s add a background using a Color view and give it a color of .lightGray. Since we want this background to sit behind everything we’ll use another kind of stack called a ZStack. You can use ZStacks to arrange views either above or below each other. Wrap the code in a ZStack{} and you should see our texts views are now above the background.

You can also try adding the ZStack using the Library Window by typing shift+cmd+L.

To extend our color view beyond the iPhone safe areas add .ignoresSafeArea(.all) to our ZStack right after the closing bracket:

SwiftUI has five built in shapes that we can use - rectangle, rounded rectangle, circle, ellipse, and capsule. The basic parts of our toggle are a capsule and a circle. Let’s start by adding a Capsule() below our Text view. To change the size we’ll use the frame modifier. Modifiers are what you use to change the appearance or behavior of a view — for ex. font styles, offsets, backgrounds, shadows, etc.

Add .frame(width:80, height:44) directly after Capsule(). To change the color add .foregroundColor(.blue).

To make your code easier to read you can put each modifier on a new line.

Now that our base is set up let’s add the knob using Circle(). Our knob needs to sit above the base view so let’s add another ZStack and wrap everything inside. Just like our base we can set the width and height of our Circle using .frame(width:40, height:40) and .foregroundColor(.white). To give it some depth let’s also add .shadow(.black.opacity(0.4), radius: 4, x:0, y:1). To reposition the knob add .offset(x:-18).

Screenshot of our basic layout in Xcode

If you’ve made it this far you may have noticed that the language and concepts are similar to what you would find in design tools like Figma and Sketch. That’s because SwiftUI uses a simple and expressive syntax that’s easy to read and write. So even if you're new to coding you can quickly get a sense of how things work.

To match the designs we need to update the colors and fonts. Starting with the background, replace .lightGray with a color literal. Color literals allow you to select a color using the Mac OS color picker instead of writing long RGB values. Start by typing Color Literal and select it in the code completion popup. The code should automatically change to a swatch that allows you to easily select differernt colors by double clicking on it. Change the background color to #393D47.

To change the color of our text views use a .foregroundColor modifier with color literals again. For font sizes and weights we‘ll use the built-in iOS font sizes of .title2 and .body.

You can view the full list of built-in type styles on Apples Human Interface Guidelines.

At this point your code and toggle should look like this (FYI color literals appear as full RGBA code outside of Xcode):

Moving onto the toggle, let’s update the base color using another color literal and include a moon image using a built-in system icon. Add Image(systemName:"moon") right after Circle(). Position the moon image over the knob by wrapping both the circle and image in another ZStack, then move the shadow and offset modifiers down to our new ZStack. We’ll also add some padding to create some space between our toggle and text by simply adding .padding(24) right after .offset(x:-18).

Now our toggle should look like this:

Looking good! In part two of this tutorial we’ll add interactions and animations to wrap things up.

Product designer @Facebook